Hibernate.orgCommunity Documentation
Table of Contents
discussions of what it means for them to be value types - lifecycle, opt-locking
Collections have the usual behavior of value types. They are automatically persisted when referenced by a persistent object and are automatically deleted when unreferenced. If a collection is passed from one persistent object to another, its elements might be moved from one table to another. Two entities cannot share a reference to the same collection instance.
Collection attributes do not support null value semantics; Hibernate does not distinguish between a null collection reference and an empty collection.
It is important that collections be defined using the appropriate Java Collections Framework interface rather than a specific implementation. From a theoretical perspective, this just follows good design principles. From a practical perspective, Hibernate (really all persistence providers) will use their own collection implementations which conform to the Java Collections Framework interfaces.
collection of values - elements can be of any value type except for collections (in fact even compositions as the element cannot contain collections) * basics * compositions
Notice how all the previous examples explicitly mark the collection attribute as either ElementCollection, OneToMany or ManyToMany. Collections not marked as such, or collections explicitly maked with @Basic are treated as JPA basic values. Meaning there value is stored into a single column in the containing table.
This is sometimes beneficial. Consider a use-case such as a VARCHAR column that represents a delimited list or set of Strings.
Example 5.1. Delimited set of tags
@Entity public static class Post { @Id public Integer id; @Basic @Type( type = "delimited_strings" ) Set<String> tags; } public static class DelimitedStringsType extends AbstractSingleColumnStandardBasicType<Set> { public DelimitedStringsType() { super( VarcharTypeDescriptor.INSTANCE, new DelimitedStringsJavaTypeDescriptor() ); } @Override public String getName() { return "delimited_strings"; } } public static class DelimitedStringsJavaTypeDescriptor extends AbstractTypeDescriptor<Set> { public DelimitedStringsJavaTypeDescriptor() { super( Set.class, new MutableMutabilityPlan<Set>() { @Override protected Set deepCopyNotNull(Set value) { Set<String> copy = new HashSet<String>(); copy.addAll( value ); return copy; } } ); } @Override public String toString(Set value) { return null; } @Override public Set fromString(String string) { return null; } @Override public <X> X unwrap(Set value, Class<X> type, WrapperOptions options) { return null; } @Override public <X> Set wrap(X value, WrapperOptions options) { return null; } }
See the Hibernate Integrations Guide for more details on developing custom value type mappings. Without the special type mapping above the "set of tags" would have simply been marshalled using serialization.