Hibernate: how to make the passed entity Persistent - java

I have a method like below:
#Override
public <T extends Entity> T saveOrHibernateUpdate(T entity) {
if (entity.getId() == null) {
persist(entity);
} else {
getSession().update(entity);
}
return entity;
}
I want to use getSession().merge(entity) instead of getSession().update(entity) inside else condition.
But this method is already being used by other applications. To not effect others, the entity which is passed to this method should still remain persistent, how can I achieve this when I am using merge instead of update? Because merge will not make the passed entity as persistent. Any ideas?
Example:
let's say someone is using previous version of this method like below
person.setName("ABC");// cosider person as a detached instance with a different name
saveOrHibernateUpdate(person);
person.setName("DEF") // They don't need to call the saveOrHibernateUpdate method again after this statement because person is a persistent object. But if I change the logic to use merge instead of update, then the users of this method would still see the name as "ABC". `So I need to make person object persistent somehow`

Hibernate merge() can be used to update values. Although this method creates a copy from the passed entity object and return it. The returned object is part of persistent context and tracked for any changes, passed object is not tracked. So you can do the following:
#Override
public <T extends Entity> T saveOrHibernateUpdate(T entity) {
if (entity.getId() == null) {
persist(entity);
return (T) entity;
} else {
Entity pEntity = (Entity) getSession().merge(entity);
return (T) pEntity;
}
}
By this way you will have the persistent object pEntity for many further manipulations.

Related

Pattern to break up external API calls?

I am trying to wrap my mind around how I would go about implementing this specific problem. We have an external API that performs some logic and returns back the result of that logic. Unfortunately, the API returns a new object as the result as opposed to just the part that I am interested in. For example, the code would look something like this:
public class ComplexObject {
//lots of fields
}
public interface LogicApplier {
LogicResult applyLogic(ComplexObject obj);
}
public class LogicResult {
ComplexObject result;
public ComplexObject getResult();
}
public class FirstImplementation {
private LogicApplier _applier;
public Implementation(LogicApplier applier) {
_applier = applier;
}
public ComplexObject mainImplementation (ComplexObject apply) {
LogicResult logicResult = _applier.applyLogic(apply);
ComplexObject newComplexObject = logicResult.getResult();
//Do some other stuff with new ComplexObject
}
}
So question is: what would be the best way to put a limit on LogicApplier's "power" over FirstImplementation? For example, our motivation to call logic in the first place is to derive a missing field, let's say "name". This field could potentially be different in, say, SecondImplementation where that implementation is now looking to derive "street address" from LogicApplier API. However, there is nothing to stop LogicApplier from changing some other field, say "idNumber".
Is this best solved by a adding an interface for our specific implementations and manually mapping fields? Something like:
public interface SecondImplementationLogicApplier {
public String deriveAddress(ComplexObject o);
}
public class LimitedImplementationLogicApplier implements FirstImplementationLogicApplier, SecondImplementationLogicApplier {
LogicApplier _applier;
public LimitedImplementationLogicApplier(LogicApplier applier) {
_applier = applier;
}
public String deriveFirstName(ComplexObject o) {
LogicResult res = _applier.applyLogic(o);
return res.firstName;
}
public String deriveFirstName(ComplexObject o) {
LogicResult res = _applier.applyLogic(o);
return res.address;
}
}
I think you are on right track with your LimitedImplementationLogicApplier. You should guard objects in your domain from possible corruption from the outside. Only update fields that you need.
It looks like your ComplexObject is mutable. I'd consider hiding it behind the immutable interface (that don't have any setters or way to change the object exposed) and pass immutable interface into your LimitedImplementationLogicApplier so its got no chance of mutating ComplexObject.
If your API requires ComplexObject type and you can't change that, to prevent mutation you could:
Option 1
Create a clone of your base ComplexObject instance and pass it into the API. After you've got the result back, you update the needed fields on untouched base instance. This will work nicely if ComplexObject is "thing in itself" and changes in its state does not have side effects outside of the class instance, like changing databases or affecting other state.
If mutation of ComplexObject has side effects or may have them in future then its a real trouble.
Option 2
Inherit a ReadonlyComplexObject class from ComplexObject and pass that into the API. In ReadonlyComplexObject you will suppress all the behavior of the parent to prevent modification.
This is hacky in my opinion and will create more work later - if ComplexObject will be extended with new properties later you will need to make changes to ReadonlyComplexObject otherwise mutation will still occur.

Hibernate: How to model an Inheritance type structure and do operations without explicit casting

I have an application that consumes incoming messages, parses the data present in the message, and then applies rules to that data. On the Rule entity, there's a column that distinguishes the type of rule.
I want to persist the Result of the rule to separate tables or subclasses, depending on what type of Rule processed them.
I'm currently solving this by creating a parent #MappedSuperclass (abstract) BaseResult object and an AppleResult and OrangeResult #Enitiy that extends the BaseResult.
My question is, given the statement below, how can I improve/annotate my objects in the model so that I don't have to do an instanceof check for each instance as I go to access/persist it? Right now this is what I'm having to do to avoid "baseresult does not exist" SQL grammar exceptions:
public void save(BaseResult baseResult) {
if (baseResult instanceof AppleResult) {
jpaApi.em().merge((AppleResult) baseResult);
} else if (baseResult instanceof OrangeResult) {
jpaApi.em().merge((OrangeResult) baseResult);
}
}
I'm hoping there's a more elegant solution than having to do a if/else and explicitly cast depending on the result. I've looking into using things like #DiscriminatorValue annotation of using Generics, but these all seem to require that the BaseResult in my case is also an entity, which it's not.
You should use #Inheritance. Then, saving would be as simple as:
public void save(final BaseResult baseResult) {
jpaApi.em().merge(baseResult);
}
Which inheritance strategy to use depends on your current database design, but I'm guessing that you have a table for each of the subclasses, so something like this:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseResult {
//...
}
#Entity
public class AppleResult extends BaseResult {
//...
}
Having #Entity on the superclass is not a problem, as it is abstract anyways..
Also, using merge is usually something one shouldn't do, you should just manipulate your entities within a transaction and it's automatically persisted in the database upon commit of the transaction:
#Transactional //either this...
public void doStuff(final ResultCommand command) {
//begin transaction <-- ...or this
final BaseResult result = em.find(BaseResult.class, command.getResultId());
result.apply(command);
//end transaction
}

Domain to Model classes

I am writing some code that will serve a website and I have some questions about my "architecture".
Domain I have a database and and at the lowest level I have the **Domain* *package that contains the classes that represent the tables of the database. I use Hibernate and lazy fetch for relationships.
Access This package has all the classes that perform database actions on the domains. I guess this is the equivalent of DAO. I get entries using the primary key, return all the entries in a table, perform a query on it. Everything is returns as a domain class or a collection of it.
Service This packages has the class (again related to a domain class each) that has more complex logic. It uses the Access package to get domain objects and transform them to model objects where model is what I call classes that represent an equivalent domain class but without the members that have relationships on them like *ToMany which would possibly have hibernate proxies that cannot be serialised and also make the object "heavier". In the future I might write custom methods/transformation to turn those collections of domain object to something descriptive for presentation but for now I disregarde them.
Model This package has the exact same number of classes as the Domain and like I mentioned is the a representation of the domain objects to something I can use for presentations, transmit, etc. (This is like parallel to the other hierarchy not part of the order.)
Servlet This packages contains all the Servlets for the websites and each servlet contains the code for something the website wants to do. It uses the service classes to get the data it wants to manipulate. The service classes will get the relevant domain objects and transform them to model objects which will be returned to the servlet classes that will perform the operations needed by the website request and then return to the website the data in JSON format.
So obviously I would like some feedback to this approach and my following thoughts.
1) I think the service classes should have only code having to do with transforming the domain object to a model object. I am thinking of using Dozer and just add code that might be needed for something more complex that Dozer can't do (basically the in the future bit). From what I saw since my model classes are basically domain classes without the heavy stuff and the members have the same name I don't even need annotations or xml.
2)In the Access I use as a parameter the base class of all domain classes so I can have an abstract class and implement all the common methods in there like so
public abstract class DomainAccess<T extends Domain> {
protected abstract Logger getLogger();
protected DatabaseFacade db;
protected Class<T> domainClass;
#Inject
public DomainAccess(DatabaseFacade databaseFacade, Class<T> domainClass) {
this.db = databaseFacade;
this.domainClass = domainClass;
}
#SuppressWarnings("unchecked")
public T fetchByPrimaryKey(Object primaryKey) {
return (T) db.find(domainClass, primaryKey);
}
// TODO This might be better to be used for complete comparison if expanded
public boolean exists(T object) {
return fetchByPrimaryKey(object.getPrimaryKey()) == null ? false : true;
}
public void save(T object) {
db.save(object);
}
public void merge(T object) {
db.merge(object);
}
public void delete(T object) {
db.remove(object);
}
public void saveOrUpdate(T object) {
if (exists(object)) {
merge(object);
} else {
save(object);
}
}
public void deleteByPrimaryKey(T object) throws EntityNotFoundException {
Object primaryKey = object.getPrimaryKey();
T objectToDelete = fetchByPrimaryKey(primaryKey);
if (objectToDelete == null) {
getLogger().debug("There was no entry found with primary key: " + primaryKey);
throw new EntityNotFoundException("No entry was found with specified primary key [" + primaryKey + "]");
} else {
getLogger().debug("Deleting entry with id: " + primaryKey);
delete(objectToDelete);
}
}
#SuppressWarnings("unchecked")
public List<T> getResultList(String hql, String... parameters) {
TypedQuery<T> query = db.createTypedQuery(hql, domainClass);
for (int i = 0; i < parameters.length; i++) {
query.setParameter(i + 1, parameters[i]);
}
return query.getResultList();
}
#SuppressWarnings("unchecked")
public T getSingleResult(String hql, String... parameters) {
TypedQuery<T> query = db.createTypedQuery(hql, domainClass);
for (int i = 1; i <= parameters.length; i++) {
query.setParameter(i, parameters[i - 1]);
}
return query.getSingleResult();
}
}
3) Similarly I think in the Service I think i shoud use the Model as a parameter like
public abstract class DomainService {
protected abstract Logger getLogger();
protected final Validator validator;
protected DomainService() {
// TODO this might be needed only for insertion so instead of a class member, maybe it's better to have it as
// a method variable?
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
this.validator = factory.getValidator();
}
/**
* Inserts an entry in the database for the object passes an an argument.
*
* #param object The object representing the entry to be inserted
* #throws ValidationException When the object doesn't pass the validation. i.e. a member value is not valid based
*/
//TODO handle validation exception with message
abstract public void insert(T object) throws ValidationException;
/**
* Deletes an entry from the database. A whole object of the appropriate type is passed as an argument which
* will be used as a storage/collection of the attributes of the entry by which the deletion can occur. Different
* implementations can use these attributes to performs filtering and collection of entries to be deleted.
*
* #param object An object representing the entry to be deleted.
*
* #throws EntityNotFoundException when no entry to be deleted is found
*/
// TODO remove TransactionRequiredException, IllegalArgumentException
abstract public void delete(T object) throws EntityNotFoundException;
/**
* Returns all the entries of the table.
*
* #return a list containing objects representing all the entries in the table.
*/
abstract public List<T> fetchAll();
}
So, in the servlet where I will have all the values for an object I will construct a member instance and then pass that down to the service which will transform it to a domain or use it to update an existing domain object (it was retrieved form the database for instance) and so on

Hibernate check deletion constraints

I am using Spring - Hibernate to control models in my application. The models are linked to each other (one-to-many, many-to-many, almost kinds of relationships), and now I have a problem when deleting one entity which is being used by other entities. The problem is I want to show the detail message that informs exactly what other objects (type, name) are using the entity that I am going to delete. It's not the common message about Constraint violation that Hibernate throws me.
For example: Car --> Person, House --> Person; then when I delete one Person who has a car and house, the message will show "There are Car (named Ford Mustang) and House (named MyHouse) linked to this Person".
1. So is there any method from Hibernate support this requirement? I guess there's no implementation for this specific requirement.
2. If not any utility available for this problem, I am thinking about below solutions:
- in each entity class (i.e Person), I will define all checking method that detect linking from the this entity to other entities, for example:
class Person {
// Properties
// Checking methods, return type and name of linked objects
public Map<String, String> getLinkedCars() {
// Query to DB to get linked cars
// return a Map contain Class name along with object name <Car, Ford Mustang>
}
public Map<String, String> getLinkedHouses() {
// Query to DB to get linked houses
// return a Map contain Class name along with object name <House, MyHouse>
}
}
-and then, in service before deleting Person entity, I will use reflection mechanism to collect results from checking methods (whose name is started with "getLinkedXXX"), and build the detail error messages.
So is this solution good? About the performance, and the convention of MVC (because I have to query data inside model class)?
Thank you for your help.
One (not so simple) approach is to scan your entity class for #OneToMany or #ManyToMany annotated fields and perform checking so neat error message can be provided to user. Following sample code assumes you only annotate the field, not the getters method, eg:
public class Person {
#OneToMany(..)
private List<House> houses;
//...
}
First get the list of all fields using reflection:
Fields[] fields = Person.class.getDeclaredFields();
Then iterate and check for #OneToMany or #ManyToMany annotations
for(Field f : fields) {
if( f.getAnnotation(OneToMany.class) != null ||
f.getAnnotation(ManyToMany.class) != null) {
// Here you know f has to be checked before the person is deleted ...
}
}
The value of a field of a particular person object can be obtained using:
Person p = // fetch a person ..
Field f = // assume f is the "List<House> houses" field
List<House> houses = (List<House>) f.get(p);
I had a similar problem, I had to check if an entity could be safely deleted to avoid foreign key constraint violations. This is how I solved:
First, I created an annotation to mark the entity that needs to be checked before deletion:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Constraint(validatedBy = SafeDeleteValidator.class)
public #interface SafeDelete {
String message() default "{lima.jefferson.SafeDelete.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Then I created another annotation to be applied to any method that will be used to check if the entity can be deleted:
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface CheckForDelete {
}
In the entity class I used these annotations like this:
#SafeDelete(message = "Couldn't delete this entity due to...")
public class MyEntity {
#CheckForDelete
public Boolean checkForDelete() {
// Insert your business logic here
return true;
}
}
And finally, the validator for the SafeDelete annotation:
public class SafeDeleteValidator implements ConstraintValidator<SafeDelete, Object> {
#Override
public void initialize(SafeDelete constraintAnnotation) {
}
#Override
public boolean isValid(Object object, ConstraintValidatorContext context) {
Method[] methods = object.getClass().getMethods();
return Arrays.stream(methods)
.filter(m -> m.getAnnotation(CheckForDelete.class) != null)
// Deal with the exception here
.map(m -> (Boolean) m.invoke(object))
.reduce(true, (a, b) -> a && b);
}
}
Then you can follow the answer of this question to apply the validation to deletion only.

jpa inheritance and code reuse in service classes

I have a parent entity, Person, and two children entities : Caller and Employee. The two children share a lot of fields so i implemented JPA inheritance with single table strategy and discriminator column.So far so good.
In order to handle these objects i have some Service classes that handle database operations where i have methods like : getCallerById(); or getEmployeesByFirstName(). Also the save() methods are in these service classes. The problem is that when i want to save an employee or an caller i got a lot of duplicate code (for all the shared properties), so in order to prevent this i created a 3rd service: PersonService() in order to handle the common functionality. But now i do not know how to use this service in order to reuse as much code as i can.
Maybe in the PersonService() to have something like
public Boolean save(Person p){
if (p instanceOf Caller){
Caller c = new Caller();
c.setCallerSpecificProperty("XXX");
}
if (p instanceOf Employee){
Employee c = new Employee()
c.setEmployeeSpecificProperty("YYY");
}
c.setOtherCommonParameter("ccc");
//............
}
or how do you advise me to handle this problem???
Thanks
if your problem is just to set the 100 commonProperties of Person, you can add helper method, say
protected Person setCommonProperties(Person p){
p.setFoo(foo);
p.setBar(bar);
...
p.setWhatever(blahblah);
return p;
}
in your parentService( PersonService in your case)
And in your sub classes, (e.g. CallerService),
boolean save(){
Caller caller = new Caller();
caller = setCommonProperties(caller);
caller.setCallerPropertyA(...);
caller.setCallerPropertyB(...);
...
//save caller
return true or false;
}

Categories