I'll take a shot at some of these.
Quote:
As I understand it so far, you can't really design straight forward Java classes as you would do without persistence and then just pass them (or better: their instances) to hibernate and say: "Go persist it!". Things like collections and inheritence need some special treatment and constraints in hibernate, as it turned out.
So instead you have to create Hibernate-compatible "entity classes" (that's how we call them) which use only Java constructs that Hibernate can handle and that your actual program/classes have to be built around.
I would say just the opposite. When I'm designing code, I write the classes first and go map them in Hibernate after I'm satisfied with the class design. For the most part--given well-designed classes--Hibernate can do its job with little to no intrusion.
Quote:
So for me, the question came up:
Exactely what Java constructs can Hibernate handle in its OR-Mapping and what not?
By "handle", I mean: create appropriate tables, save the object and load it again, ensuring full referential integrity int the object tree, etc.
That's a very broad question. My answer would be that Hibernate can handle virtually anything you would write in a production Java app.
[...]
Quote:
Limitations I know so far:
Collections
- Hibernate can only persist collections by the type of the class field that references them and the field type must be a collection Interface (Like java.util.List.class etc).
So you can't write a class field like
Code:
private ArrayList<String> myStringList;
That's correct, but what you're suggesting is a very poor practice anyway. For collections in particular and inheritance hierarchies in general, you should always default to using interface types and only refer to objects by their concrete types when you have a clear need for it. Therefore, Hibernate is designed specifically to handle the preferred method of working with collections: typing them as Collection, List, Map, or Set.
Quote:
- afaik, Hibernate can't handle nested collections (Like HashMap<Integer, HashMap<String, String>> for example)
To my knowledge, this is correct; however it's not much of a limitation because most of the time you'll find that if you think you need a collection of collections, there's actually an intermediate entity that you should create to represent the relationship and contain information about it, not to mention giving it better organization and making it easier to understand and work with.
Quote:
- Hibernate always replaces the actual type of the Collection by a compatible collection type of its own, so the actual type is lost/not reliable on by the programm (behaviour- and reflection-wise)
Again, you should never care that something is an ArrayList, only that it's a List. That removes this problem.
Quote:
Generalisation
- Hibernate can't handle a class field that is just of type Object
So for example this:
Code:
private Object anyReference = new MyPersistentClass();
Won't be handleable by Hibernate. Is that correct?
(note: yes i know that you "should" not do this in general. I of course don't do this in general. It's more about the question: can it be handled without a hitch if the rare case occurs that it has to be done for some reason)
No, this is incorrect. Hibernate cares little about the declared type of the variable, though you'd have to take an extra configuration step to inform Hibernate what the "type" of this field is because it won't be able to figure it out on its own. Besides that, as long as the persistent instance is assignable to it, everything's fine, and of course anything is assignable to Object.
Quote:
Unclear Java Features:
Class field with superclass type
Say I have the following class field:
Code:
private MyPersistentSuperClass someReference;
Can Hibernate handle the actual instance that this field will reference no matter what concrete type it will be during runtime?
For example:
Code:
someReference = new MyPersistentSubClass();
or
Code:
someReference = new MyOtherPersistentSubClass();
etc...
Class field with interface type
Same as the point above for Interfaces:
If I have a "private MyInterface someReference;", can Hibernate handle instances of persistent classes that are referenced by this field?
Like, again:
Code:
someReference = new MyPersistentSubClass(); // MyPersistentSubClass implements MyInterface
Absolutely. As I said before, Hibernate cares little about the declared type of a property. It just saves/loads what's actually there, and as long as the object it persists is assignable to the variable that's intended to hold it, everything's fine.
Quote:
Arrays
Can Hibernate handle multi-dimensional arrays?
Like:
Code:
private MyPersistentSubClass[][][] my3d = ...
?
I don't believe so. It's like the collection of collections thing.
Quote:
And what about referential integrity after loading when sub-arrays of multi-dimensional arrays are referenced elsewhere?
Like:
Code:
private MyPersistentSubClass[][] my2d = my3d[0]
So after saving and loading both arrays (to and from the db of course, not only the cache), will my2d and my3d[0] still point to the SAME two-dimensional array instance?
Problems like this are probably part of the reason that Hibernate doesn't support things like multi-dimensional arrays and collections of collections, not to mention that these things often indicate a poorly-designed object model and tend not to make it into production code, so there's little demand for these features.
On the referential integrity front, the second level cache, which I assume you were talking about, has nothing to do with the discussion. Objects are "dehydrated" before being stored in the cache. The actual object instances are not stored, and when an object is retrieved from the cache, you always get a new, separate instance.
There is, however a first-level cache--the Session--which ensures that if you load the same entity twice, you'll get the same instance both times.
Quote:
Inner Classes
Can instances of inner class (which reference an instance of their outer class) be handled by hibernate?
Inner Static Classes
Can instances of inner static class be handled by hibernate?
Inner classes, no. Static nested classes, which technically are not inner classes, yes. To map a class in Hibernate, it must be instantiable on its own, which an inner class is not.
Quote:
Hm. I'm not sure if these are all points. At least for now I can't think of anything else...
Thanks for answers!
One final note: for the situations you mentioned that Hibernate doesn't actually support, you can always write a custom
UserType to map any kind of data structure you want to the database.
HTH
Ryan