We recently joined up to an existing project and in several entity classes we have seen the following code example:
#OneToMany(mappedBy = "department")
private List<Employee> employee= new LinkedList<>();
I had a discussion with a developer about using ArrayList instead of LinkedList for hibernate. But the arguments from both sides were not clear enough.
Usually, i use for many purposes an ArrayList. Here is a good comparison
Does hibernate under the hood work better with that?
Is there a reason why linkedList is used?
Or has it simply been used unknowingly in the project?
The actual implementation used when an entity is loaded from the database is not the same as the default value in the class definition. This is why entity properties which are collections must be specified as an interface type.
Hibernate uses its own collection implementations which are enriched with lazy-loading, caching or state change detection semantics. For this reason, persistent collections must be declared as an interface type.
From https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#collections
If your entity is not loaded from the database then you should specify a default implementation that make sense for the use case, but being aware it'll not be the same implementation when the entity is loaded. Generally, this means just using ArrayList in most situations.
Related
I've been dealing with this, now i want to take control of this. Due to data size, I have to control the list which was populated by Hibernate.
#OneToMany(mappedBy="members")
private List<Members> membersList;
So the memberList can grow upto 100, The Sql of android cannot not take it. I meant the huge size of list stored to internal database.
Is there anyway to control the list size before saving to android internal database?
Thanks,
Pusp
you need to set your type of collection.
#OneToMany(mappedBy="members")
private Set<MembersList> memberList;
UPDATE
The documentation says:
Naturally Hibernate also allows to persist collections. These persistent collections can contain almost any other Hibernate type, including: basic types, custom types, components and references to other entities. The distinction between value and reference semantics is in this context very important. An object in a collection might be handled with "value" semantics (its life cycle fully depends on the collection owner), or it might be a reference to another entity with its own life cycle. In the latter case, only the "link" between the two objects is considered to be a state held by the collection.
As a requirement persistent collection-valued fields must be declared as an interface type (see Example 7.2, “Collection mapping using #OneToMany and #JoinColumn”). The actual interface might be java.util.Set, java.util.Collection, java.util.List, java.util.Map, java.util.SortedSet, java.util.SortedMap or anything you like ("anything you like" means you will have to write an implementation of org.hibernate.usertype.UserCollectionType).
Link: https://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/collections.html#collections-mapping
AppEngine only supports "TABLE_PER_CLASS" and "MAPPED_SUPERCLASS" for JPA inheritance.
Unfortunately "JOINED" and especially "SINGLE_TABLE" are not supported.
I'm wondering what the best alternative is to implement a SINGLE_TABLE alternative?
My only requirements are:
1) Have separate classes like AbstractEmployee, InternalEmployee, ExternalExmployee.
2) Being able to run a query over all employees, thus resulting in both InternalEmployee and ExternalEmployee instances.
The only thing I'm thinking off is using a 'big' Employee object containing all fields?
Any other ideas?
PS: vote for proper "SINGLE_TABLE" support via http://code.google.com/p/googleappengine/issues/detail?id=8366
You could in theory use #Embeded and #Embeddable to group related fields into an object. So you would have a class that looks something like.
#Entity
public class Employee {
// all the common employee fields go here
//
// the discriminator column on Employee class lets you be specific in your queries
private Integer type;
#Emebded
private Internal internal; // has the fields that are internal
#Embeded
private External external; // has the fields that are external
equals & hashcode that compare based on the discriminator type and other fields
}
What AppEngine supports and doesn't support is misleading there. AppEngine uses a property store, so any Kind can have any properties. Consequently, in principle, a Kind can contain InternalEmployee and ExternalEmployee "instances". The only thing that AppEngine JPA actually does is store all fields of a class in a single Kind object. That doesn't preclude having subtypes stored in the same Kind (with extra properties for the subtype-specific fields), which is the equivalent of "single-table".
PS, raising some issue on "AppEngine" as a whole won't get any response (look at the rest of issues in there ;-) ), bearing in mind the code affected here is in its own project at http://code.google.com/p/datanucleus-appengine and has its own issue tracker
One of my goals is to create an engine that will set values in pojo object from JPA objects dynamically using reflection. One of the matching criteria is, that the field names should match.
I was successfully able to implement this for two pojo objects. But when I tried using JPA objects as one of the object parameter, it didn't work. Based on my research I found out that the method Class.getDeclaredFields() , does not give me the name of the field but the getter/setter method name of member variable for JPA objects.
Can anyone please give me a lead or direction as in where/what should I look to accomplish this task?
JPA providers will often use dynamic proxy classes of your concrete JPA classes, so you have no guarantee of the field names in the proxy. The only guarantee about a proxy is that the methods are the same. Use a debugger to inspect the runtime class of the JPA class instances that you're trying to use and you'll see the problem.
The best you'll be able to do is use reflection to call methods on JPA-returned objects.
All that aside, I don't really see why you'd need to POJO-ify an entity class anyway, since an entity is primarily an annotated... POJO.
One of the matching criteria is, that the field names should match.
I think that this is the root of your problem. There is simply no guarantee that a Java object's field names will match the names of getters and setters ... or anything else. If you make this assumption, you will run into cases where is doesn't work.
The best solution is to simply not use this approach. Make it a requirement that the Pojo classes conform to the JavaBeans spec and rely on the setters to set the properties. This is likely to work more often than making assumptions about (private) field names.
In fact, the state of a generic JPA object implemented using a dynamic proxies could well be held in a hash map. Those fields you can see could simply be constants used for something else.
Does JPA ( Eclipselink in this case) always return IndirectList where Entity have a List?
Is ok that list or It should be converted to another list( maybe linkedlist)?
Analysis
If we look at EclipseLink's IndirectList's API, it says:
To use an IndirectList: declare the appropriate instance variable with type IndirectList (jdk1.1) or Collection/List/Vector (jdk1.2).
TopLink will place an IndirectList in the instance variable when the
containing domain object is read from the datatabase. With the first
message sent to the IndirectList, the contents are fetched from the
database and normal Collection/List/Vector behavior is resumed.
If we view IndirectList sources, we will see, that all the work is delegated to it's original collection, just like API says.
Answers
Does JPA ( Eclipselink in this case) always return IndirectList where Entity have a List?
Yes, it always does return your specified collection wrapped with IndirectList. Since it delegates all its internal work to the wrapped collection, it preserves the way it works.
Is ok that list or It should be converted to another list( maybe
linkedlist)?
Yes, it is okay to use IndirectList. You don't convert, you just define any type of collection you want and don't worry about IndirectList, since it is managed transparently.
Since List is an interface the JPA provider is free to return any implementation. EclipseLink rerurns an IndirectList where a List is used. This is perfectly fine since the IndirectList is a List.
For the record or for future reference, it is generally best practice to use interfaces with JPA.
Why does hibernate require it's entities to be written to an interface in order for them to work correctly with lazy loading?
The only scenario where hibernate requires interfaces is collections. It's because hibernate uses its own collection implementations for lazy loading - PersistentBag, PersistentSet, etc. and assigns them to your fields. The implementations hold a reference to the session so that they can fill their data whenever required.
Hibernate can assign PersistentSet to private Set<Foo> set; (they do it with reflection), but it is not possible to do so for private HashSet<Foo> set;, because PersistentSet does not extend HashSet
As for lazy #*ToOne associations - hibernate creates a proxy object, using javassist (or cglib), and it does not require an interface. This is a rarely used feature anyway, and the proxy is a subclass of the real object, so unless you use getclass() (which you should not do), it works fine.