Why SortedSet relationship required sorting annotions like hibernate-specific #SortNatural or #OrderBy ?
Could be great if natural ordering was used by default.
As defined in chapter 2.2 of JPA-2.2 (JSR-338):
Collection-valued persistent fields and properties must be defined in terms of one of the following collection-valued interfaces regardless of whether the entity class otherwise adheres to the JavaBeans method conventions noted above and whether field or property access is used: java.util.Collection, java.util.Set, java.util.List, java.util.Map. The collection implementation type may be used by the application to initialize fields or properties before the entity is made persistent. Once the entity becomes managed (or detached), subsequent access must be through the interface type.
Then, when retrieving data to an #OneToMany mapped field, a persistence provider implementation may use any corresponding implementation class for the given field. So, if a mapped entity defines a #OneToMany List, the persistence provider may assign the field with an ArrayList or any other concrete implementation of list, ordered or not. For interfaces not mentioned, the persistence provider may accept the mapping, but it is not required to respect it and there are no guarantees about the implementation used.
The #SortNatural proprietary annotation instructs Hibernate to use an ordered implementation of the collection type that will use the "natural comparator" of the entity to order the elements. If the contained entity type implements Comparable interface, that comparator will be the "natural" comparison method to order the given collection.
Be aware that some persistence provider implementations may or may not reuse the instantiated field to populate the collection, so, if you declared and instantiated the field with a given ordered implementation for the List or Set, it may be already ordered despite the lack of use of a hibernate-specific annotation.
The #OrderBy annotation, on the other hand, is provider agnostic and defines an order that must be respected on the retrieved list or set, but it's implementation is limited by how the database will order the field. The retrieved collection may use any implementation that preserves the order in which the data came from the database, but does not use the Comparable interface to reorder data after retrieval, as #SortNatural would.
Both approaches have their strength and hiccups, so you have to verify your use case and decide if this ordering is critical to the point of relieving it to your data layer.
Related
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.
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
I use Hibernate and want to query for entities by their natural identifier. However, it seems not to be possible to have natural ids on subtypes. I have two classes A and B where B extends A:
class A {
long id;
}
class B extends A {
String naturalId;
}
A is mapped in Hibernate with its own identifier. B is mapped as joined subclass. However, it is not possible to map the natural identifier of B in Hibernate because the mapping of B is a subclass mapping.
Why is it not possible to have a natural identifier on the subclass B? Note that I don't want Hibernate to generate my database schema, I just want to have natural ids for fast cache hits.
Is there a way/a best practice to have natural ids on subtypes for fast second level cache querying?
Is this still possible when natural ids might get updated (change) in rare circumstances and the cache has to be maintained in a clustered Java EE environment?
NaturalId only make sense for base classes, because you can't retrieve a sub-class without the base class info.
Let's say you could map map both the base class and the sub-class with a natural-id:
class A {
long id;
String baseId;
}
class B extends A {
String naturalId;
}
A a = session.bySimpleNaturalId( A.class ).load( "abc" );
If the entity we retrieve if of type B, it's not clear which of the natural-id variants will be used.
You can't fetch a sub-class without getting the base-class info. So when you load a Sub-class from cache, the associated base-class info is retrieved as well. Therefore you could have the base class store the natural-id, or simply use the primary key for caching.
You can update the natural-id, although a business key should be immutable. For mutable natural-ids you need to use the mutable attribute.
According to 13.3. Entity inheritance and second-level cache mapping:
As of Hibernate ORM 5.3, you can now override a base class #Cacheable
or #Cache definition at subclass level.
so you might have a chance by resetting the caching annotations on B.
I never tried it so please confirm the solution with a comment.
I have several JPA entities that have one-to-many relationships to other entities and therefore contain Collection fields. Obviously, as per the standard bean pattern I have getter and setter methods for these Collections but it would also be useful to have methods to add and remove objects/entities from these collections. Would I be breaking bean conventions to add these methods to the entity class themselves? If this is the case, what would be the best way of implementing these methods? I do have Facade EJBs for each entity which I could use for this purpose but these are primarily concerned with DB access logic (persist, remove, etc) and obtaining data structures (lists, etc) rather than manipulating the entity itself.
Thanks to Nikos Paraskevopoulos and Flying Dumpling for the answer. It would appear that utility methods are permissible within an entity class.
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.