org.minijax.db.DefaultBaseEntity Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of minijax-db Show documentation
Show all versions of minijax-db Show documentation
Minijax database and entity model
package org.minijax.db;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.time.Instant;
import java.util.Objects;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import org.minijax.json.Json;
import org.minijax.util.IdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The BaseEntity class is the abstract base class for all web primitives.
*
* ID's are set by the class. ID's are *not* populated by JPA.
*
* For background:
*
* - https://stackoverflow.com/questions/5031614/the-jpa-hashcode-equals-dilemma
* - http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html
*
*/
@MappedSuperclass
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class DefaultBaseEntity implements BaseEntity {
private static final Logger LOG = LoggerFactory.getLogger(DefaultBaseEntity.class);
private static final long serialVersionUID = 1L;
@Id
@Column(columnDefinition = "BINARY(16)")
@Convert(converter = UuidConverter.class)
private UUID id;
@Convert(converter = InstantConverter.class)
@SuppressWarnings("squid:S3437")
private Instant createdDateTime;
@Convert(converter = InstantConverter.class)
@SuppressWarnings("squid:S3437")
private Instant updatedDateTime;
@Convert(converter = InstantConverter.class)
@SuppressWarnings("squid:S3437")
private Instant deletedDateTime;
protected DefaultBaseEntity() {
id = IdUtils.create();
}
/**
* Returns the ID of the object.
*
* @return
*/
@Override
public UUID getId() {
return id;
}
/**
* Sets the ID of the object.
*
* @param id
*/
@Override
public void setId(final UUID id) {
this.id = id;
}
/**
* Returns the date/time when the object was created in the database.
*
* @return The created date/time.
*/
@Override
public Instant getCreatedDateTime() {
return createdDateTime;
}
/**
* Sets the date/time when the object was created in the database.
*
* @param createdDateTime The created date/time.
*/
public void setCreatedDateTime(final Instant createdDateTime) {
this.createdDateTime = createdDateTime;
}
/**
* Returns the date/time when the object was last updated in the database.
*
* @return The updated date/time.
*/
@Override
public Instant getUpdatedDateTime() {
return updatedDateTime;
}
/**
* Sets the date/time when the object was last updated in the database.
*
* @param updatedDateTime The updated date/time.
*/
public void setUpdatedDateTime(final Instant updatedDateTime) {
this.updatedDateTime = updatedDateTime;
}
/**
* Returns whether the object is deleted.
*
* Data is never truly deleted from the database. It is the responsibility
* of all application logic to enforce the deleted flag as appropriate.
*
* @return True if the object is deleted.
*/
@Override
public boolean isDeleted() {
return deletedDateTime != null;
}
/**
* Marks the entity as deleted.
*
* Shortcut for setDeletedDateTime(Instant.now())
.
*
* @param deleted True if the object is deleted.
*/
@Override
public void setDeleted(final boolean deleted) {
deletedDateTime = deleted ? Instant.now() : null;
}
/**
* Returns the date/time when the object was last deleted in the database.
*
* Data is never truly deleted from the database. It is the responsibility
* of all application logic to enforce the deleted flag as appropriate.
*
* @return The deleted date/time.
*/
@Override
public Instant getDeletedDateTime() {
return deletedDateTime;
}
@PrePersist
public void onPrePersist() {
createdDateTime = Instant.now();
updatedDateTime = createdDateTime;
}
@PreUpdate
public void onPreUpdate() {
updatedDateTime = Instant.now();
}
/**
* Returns a hash code for this details object.
* The hash code is completely based on the ID.
* If a deriving class expects to mix/match several classes
* within a hash table, then you should override and replace this.
*/
@Override
public int hashCode() {
return id == null ? 0 : id.hashCode();
}
/**
* Determines if this object equals another.
* Equality is defined as same class type and same ID.
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!getClass().equals(obj.getClass())) {
return false;
}
final DefaultBaseEntity other = (DefaultBaseEntity) obj;
return Objects.equals(id, other.id);
}
public String toJson() throws IOException {
return Json.getObjectMapper().writeValueAsString(this);
}
/**
* Returns a SQL hint for super admin debugging.
*
* Note that this value *IS NOT* used in any database code. This is merely
* to help developers quickly navigate their developer databases.
*
* @return A SQL hint.
*/
public String getSqlHint() {
final String tableName = getClass().getSimpleName().toUpperCase();
final String hexId = getId().toString().replaceAll("-", "");
return "SELECT * FROM `" + tableName + "` WHERE ID=UNHEX('" + hexId + "');";
}
/**
* Copies all non-null properties from the other object to this object.
*
* @param other The other entity.
*/
public void copyNonNullProperties(final T other) {
if (!getClass().equals(other.getClass())) {
throw new IllegalArgumentException("Incorrect type (expected " + getClass() + ", actual " + other.getClass() + ")");
}
Class> currClass = getClass();
while (currClass != null) {
for (final Field field : currClass.getDeclaredFields()) {
copyNonNullField(other, field);
}
currClass = currClass.getSuperclass();
}
}
private void copyNonNullField(final T other, final Field field) {
if (Modifier.isStatic(field.getModifiers())) {
return;
}
if (field.getName().equals("id")) {
return;
}
try {
field.setAccessible(true);
final Object value = field.get(other);
if (value != null) {
field.set(this, value);
}
} catch (final IllegalAccessException ex) {
LOG.error(ex.getMessage(), ex);
}
}
public static T fromJson(final Class c, final String str) throws IOException {
return Json.getObjectMapper().readValue(str, c);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy