Is it possible to have following collection mapping in JPA / hibernate
#OneToMany(cascade={CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE},
fetch=FetchType.LAZY,mappedBy="parent")
private Deque<Child> childrens;
It throws error
Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements
I am using JPA 2.0 with Hibernate 3
No, JPA does not support Deque. In JPA 2.0 specification this is explained following way:
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[3], java.util.Map. The collection implementa- tion 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.
I would suggest to add to entity methods that provide needed Deque functionality (or expose view as Deque to persisted list). Other possibility is custom collection as suggested in comments (Thor84no).
While JPA does not support Deque as mentioned by Mikko, you could simply update your code to be an ArrayDeque and you should be good to go.
#OneToMany(cascade={CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE},
fetch=FetchType.LAZY,mappedBy="parent")
private ArrayDeque<Child> childrens;
Related
In this article http://www.jroller.com/eyallupu/entry/hibernate_the_any_annotation and also in this question How to use Hibernate #Any-related annotations?, how #Any annotation can be used was explained. But how can I get borrows for each DVD/VHS/BOOK? How can I do mapping definition on DVD/VHS/BOOK?
I don't think this is supported and, as mentioned in the documentation:
2.4.5.2. #Any
The #Any annotation defines a
polymorphic association to classes
from multiple tables. This type of
mapping always requires more than one
column. The first column holds the
type of the associated entity. The
remaining columns hold the identifier.
It is impossible to specify a foreign
key constraint for this kind of
association, so this is most certainly
not meant as the usual way of mapping
(polymorphic) associations. You should
use this only in very special cases
(eg. audit logs, user session data,
etc).
While I understand that this annotation has been introduced to map an association property to different types of entities that don't have a common ancestor entity, I think it would be better to introduce a base type the other entities would inherit from for bidirectional relations.
See also
#Any bidirectional relationship fails
Yes, the problem with bi-directional associations where one side is polymorphic (mapped with #Any or #ManyToAny), is that Hibernate auto-generates an invalid foreign key. Personally, I view this as a bug, not a usage error.
You can get around this by specifying the foreign key explicitly, i.e. not rely on Hibernate to infer it. In the Borrow <--> DVD/VHS/Book example, let's say you want a bi-directional, many-to-one association between Borrow and DVD/VHS/Book (the "item"), then you map it on the Borrow side with the polymorphic #Any mechanism to item, and on the item side with a #OneToMany to Borrow.
BUT: on the latter property/getter, you also specify, explicitly, the join column to use, e.g. "ITEM_ID". That should force Hibernate to use only "ITEM_ID", and not (as I've seen) ITEM_ID + ITEM_TYPE that it infers by default from the #Any definition on the other side.
If you don't have a "Item" superclass for DVD/VHS/Book, you'll have to declare this in each class, something like:
#Entity
class Book {
...
#OneToMany
#JoinColumn(name="item_id")
public List<Borrow> getBorrows() {
return this.borrows;
}
}
For example I have a following class structure
class Parent {
fetch = FetchType.EAGER
List<Child> children;
}
class Child {
fetch = FetchType.LAZY
List<SuperChild> superChildren;
}
The question is
when I fetching Parent object, e.g:
ParentRepository::findById();
Will superChildren be fetched because of their parents EAGER or their LAZY overrides it?
Nothing about the documentation of FetchType implies any behavior with regards to an associated entity's own FetchType. Note even the description of LAZY (this is from the documentation of the JPA specification):
"The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified."
So as a side note, in general LAZY may not be guaranteed depending on the implementation provider.
Hibernate (the most popular JPA implementation) will lazily fetch superChildren, so the FetchType of Parent#children will not matter. I haven't tried with other implementations but I highly doubt it will differ.
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.
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'm trying to avoid hibernate's lazy-loading mechanism and I've created this list object with the Eager FetchType, which I would suppose would do it:
#JsonIgnore
#CollectionTable(name = "nav", joinColumns = #JoinColumn(name="conn"))
#ElementCollection(fetch = FetchType.EAGER)
#IndexColumn(name="filter") private List<String> filters = Lists.newArrayList();
But I'm still reading a PersistentList, instead of java.util.List. Any idea on what may be wrong ?
I'm not using xml configurations.
A Persistent List is a non-lazy collection that Hibernate uses to correctly store and retrieve data from the databases. It is not a case that when you define your persistable entities you cannot use Java collection implementations, such as ArrayList or LinkedList, but only interfaces. In fact, you are asking for a List and you are getting PersistentList, which totally respect the contract of the interface.
If you remove the eagerness and debug your class, you will see a lazy collection appearing, and this is typically a CGLIB proxy.
To avoid lazy loading you have to set lazy = true and instead of FetchType.EAGER make it FetchType.JOIN.
for annotations based mapping refer to the below link:
[http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-hibspec-singleassoc-fetching]
let me know if it helps you.