persisting object to database with ORM - java

Within an Entity class, can I have any object as an attribute and when I persist the Entity to the database will it also persist that objects attributes?

If the object is serializable, you could serialize it as a BLOB. But that's not something you want to do because
it would be inefficient to constantly serialize and deserialize the object
it would be very fragile: a change in the object class would make it impossible (or hard if you know what you're doing) to read previous versions already saved in the database
only Java could make sense of the blob
you could not do any query on this object
So, basically, the answer is no. JPA entities can have embedded objects, whose fields are mapped to columns, or can have associations with other entities (OneToOne, OneToMany, ManyToOne or ManyToMany).
My advice: think about the design of your database first, then map the schema to JPA entities. If you start writing an object model without even thinking how it will be persisted in the database, you won't go very far.

Related

Updating a single entity without affecting its dependencies in Hibernate

Consider the following scenario:
I have a Person entity that has a many-to-many relationship with Group entity and a many-to-many relationship with Role entity. Both entities have bidirectional relationship with Person setting CascadeType to SAVE_UPDATE. The FetchType is set to LAZY.
Person also has attributes like name, birthdate, id, etc.
Since I'm working in a heavy transactional multithreaded environment, as a design consideration, when a certain Person attribute is going to be modified, the Person object retrieved through hibernate session's get method is being copied using the following method:
public Person personCopyWithoutDependencies(Person entity){
Person person = new Person();
person.setId(entity.getId());
person.setName(entity.getName());
person.setBirthdate(entity.getBirthdate());
person.setGroups(null);
person.setRoles(null);
return copy;
}
Then, I do Person's specific attribute modification in the copy object and then call the Hibernate session's Update method. The copy is done to prevent issues with multiple sessions in multiple threads (when doing a modification sessionFactory.openSession() is called and closed after commit while when retrieving an objtect sessionFactory.getCurrentSession() is being called).
If the person object that I modified had previously associated Group and Role entities, it deletes the relationship in the database.
I want to know if it's possible to do the modification I'm intending without losing its relationships.
Thank you very much in advance. Any advice is welcome.
The only way to do this, is to validate, whats changed, and retrieve REal Hibernate object back.
Steps:
You do have a copy with some attributes. (NULL instead of Proxy lazy collections)
You do change some of them.
You retrieve Real object again from Hibernate (DB)
You map objects attributes back to real object, and just do not do this for NULL attributes.
commit changes.
This is the only way to do this. As #Gimbly mentioned, you are trying to handle, whats Hibernate suppose to do.

Use hibernate when saving objects to the database

In my java application I have some serialized entity classes with inheritance. When saving instances of these classes i am converting them to a byte array and saving to a longblob column in my database table. Is there any advantage using hibernate to implement this program. Because as far I understand hibernate is used to map entities with database tables in a proper way. But here I don't have a relational model to map attributes of entities. I am saving them as objects. Am I missing something. Please clarify me. Thanks in advance.
If you don't have a relational data model to save those objects and you can't change your schema, then you can use your current approach.
If you use PostgreSQL you might be interested in JSON storage as well. That way you can store your hierarchies using JSON objects and you can even run native SQL queries against them (although not inheritance-aware, but you can cope with that if you use some _class column to differ between object types).
The cleanest approach is to have the relation model in sync with your business domain model. That way you can benefit from:
optimistic locking (preventing lost updates phenomena)
caching (2nd level cache and query cache)
query-able hierarchies
an external DBA hierarchies could run an update on your hierarchies using mere SQL
auditing

How one to many relationship gets persisted in JPA if i have thousands of related entities already in data base and i add new entities in collection

We have two entities Entity1 and Entity2, where Entity1 contains set of Entity2,
we already have thousands of entities stored in database of entity type Entity2 which all are referenced from an instance of Entity1, say myEntity.
Now if i add more Entity2 entities to the collection and try to persist myEntity, where newly added entities of Entity2 are already persisted.
My question is how will be the behavior on persist of myEntity , whether existing members of relation will travel to memory and new members will be added or new members are added to database without bringing existing members to memory
If you have thousands of referenced entities, it might be better not to map the relationship and instead only query for it when needed - allowing you to use paging or other mechanisms to reduce the amount of entities read in at a time. It depends on what type of mapping it is, but only the owning relationship needs to be mapped (the one that doesn't have the mapped by) to set the foreign key in the database. Set the Entity2 side to be the owning side if it isn't already.
If this is a M:M with a relation table and doesn't make sense to map from the Entity2 side instead - you could add an entity for the relation table that you would read in the same way. The new entity would have a reference to Entity1, but Entity1 wouldn't reference it, and the app would query for the new entity when it needs to get Entity2s associated to a specific Entity1.
If you want to add new instances to a relation between two already existent entities (a one to many in this case) then you must first fetch from the database the entity that contains the collection; in your case myEntity.
So, when you load that entity you are bringing it to memory. If you had defined the relation between those two as EAGER then all the related entities (the ones in the collection) will be fetched as well at the same time than the parent one. If you, otherwise, had defined the relation as LAZY then the related entities will be loaded when you access the collection (in other, words, when you invoke the getter getXXX method for that collection).
This happens that way because JPA implementations (now I'm thinking on Hibernate) return proxies of the entities instead of actual instances so they can intercept the getter/setter method calls and perform any tracking on the state of the entities.
Right, so now you want to add more instances to the relation. It doesn't matter whether the relation is EAGERor LAZY in this case as you will eventually invoking the getter method of the collection in order to be able to perform add(myNewEntity); on it. So, the already existent entities are in the collection and you are just adding a (probably) untracked entity under the collection implementation semantics.
When persisting myEntity back to the database the JPA implementation will know which instances of the actual collection need either an update, a delete or an insert. If you just added new instances then just insert statements will be issued but you could also remove an entity from the collection or change the state (invoke the setter) of an already existent instance. JPA implementations are able to recognise those operations and issue the appropriate SQL statements to keep the database up to date.

Hibernate: Empty collection instead of Lazy-load error

I have an ORM entity loaded by Hibernate, with certain associations LAZY loaded when I need them. This entity is transported thru MQ to client application (and the client is .NET, so I'm using MessagePack to serialize/deserialize) and when the entity is serialized by MsgPack, it tries to access the lazy loaded association and it fails, as the session is already closed. And even if it did not failed, I do not want it to load the association in some cases.
Is there a way to tell hibernate to fill the lazy associations with empty values instead of proxies for some query results or do I have to iterate the returned list and perform these changes by myself?
Thanks for your answers!
You have no other way, but to use DTO objects, to tranfer it through MQ,
Load entity from DB using hibernate
convert it to DTO object which implents Serializable.
Transfer it to consumer using MQ
Convert it to any other entity on other side.
I think that #Transient only applies to ORM. If you do not want your field to be serialized, you should use key word "transient".
private transient List<Object> myTransientList;

What are JPA entities?

I am starting to use JPA and I always get confused with the term of entities and their usage, I have read a lot but I still don't quite get it.
I read the Oracle documentation of it but it does not really explain its role in the transaction.
What are JPA enities? does they actually hold the data for each row, I mean, are they stored instances that hold the row data? or they just map tables of the db and then insert and delete in them?
for example if I use this:
entity.setUserName("michel");
Then persisting it, then changing the user name, and persisitig it again (i.e merging it)
Does this change the previously entered user name? or does it create a new row in the db?
An Entity is roughly the same thing as an instance of a class when you are thinking from a code perspective or a row in a table (basically) when you are thinking from a database perspective.
So, it's essentially a persisted / persistable instance of a class. Changing values on it works just like changing values on any other class instance. The difference is that you can persist those changes and, in general, the current state of the class instance (entity) will overwrite the values the row for that instance (entity) had in the database, based on the primary key in the database matching the "id" or similar field in the class instance (entity).
There are exceptions to this behavior, of course, but this is true in general.
It's a model. It's a domain object that can be persisted. Don't over think it. Akin to a Rails model. And remember, models (in this paradigm) are mutable!

Categories