Store List in hibernate as Serializable object - java

Normally we store a List in database by the hibernate mapping:
<list name="userItems" cascade="all" lazy="false">
<key column="user_date_id"/>
<index column="idx"/>
<one-to-many class="UserItem"/>
</list>
Is there any other way? Can we store it as a Seializable object? Like:
<property name="list" column="list" type="serializable" />

I use Hibernate Annotiations, and the trick here is to define your field as a List implementation like ArrayList. Then (like any other class implementing Serializable - i guess) Hibernate stores it as a bytea in the database.
Of course the list should only contain elements that implement Serializable.

I'm not sure you can directly serialize a list but if not you might create a wrapper object for the list and declare it as large object (don't know the xml variant, but it's the #Lob annotation). This should automatically be serialized then, since its not a string and thus not a clob but rather a blob.

Related

Hibernate use same mapping for multiple tables

I have 2 identical DB instances containing FOO_TABLE with the same schema. So, currently I have one class definition per DB instance:
<class name="FooTable" table="FOO_TABLE" entity-name="FooTableInstance1">
<property name="..." column="..." />
<property name="..." column="..." />
....
</class>
<class name="FooTable" table="FOO_TABLE" entity-name="FooTableInstance2">
<property name="..." column="..." />
<property name="..." column="..." />
....
</class>
The problem is that I don't want to copy-paste the properties, as the tables have the same schema. Is it possible to inherit the 2 classes from a base class which contains all the mappings and in the 2 children classes specify different entity-name?
An alternative (and perhaps the correct one if I understand your question correctly) is to use a #MappedSuperclass to define the common mappings. Whether you use this or the suggestion posted previously depends on the data model: for example are these two entities related so that you would like to be able to query across both of them?
e.g. select f from Foo returns all Foo1 and Foo2.
This cannot be done when Foo is a MappedSuperclass.
See here for further details:
http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Mapped_Superclasses
JPA: Implementing Model Hierarchy - #MappedSuperclass vs. #Inheritance
Yes, it is possible. Take a look at the relevant documentation: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/inheritance.html
More specifically, check 9.1.5. Table per concrete class. Make the parent class abstract and things should work fine.
According to the documentation you need 3 Java classes:
Foo (abstract, containing all fields you want in both tables)
FooChild1 (concrete, subclass of Foo, containing no new fields)
FooChild2 (concrete, subclass of Foo, containing no new fields)
You will need two tables. One mapping to FooChild1, and another to FooChild2.

Hibernate - set of compound values

I need a Collection of compound values in Hibernate. Something like:
class Parent {
Set<Child> children;
}
class Child {
String property;
String anotherProperty;
MyOtherClass oneToOneClass;
}
The key requirement is that elements in this collection are value objects. When I saveOrUpdate the Parent it also saves its children.
More importantly when I create another Parent with children based on the same set, these children need to be persisted separately. That's why regular one-to-many does not work for me.
Is there a clean way I can do it with Hibernate? Something like collection of values described here: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html - but for a concrete, compound class.
I prefer solution in XML rather than annotations.
Normally you map this as composite-element
<set ... >
<key .../>
<composite-element class="Child" ...>
<property name="property"/>
<property name="anotherProperty"/>
<nested-composite-element name="oneToOneClass">
<property name="..."/>
</nested-composite-element>
</set>
See Component Mapping.

Hibernate type used to map java.lang.Double

I am using "double" in Hibernate .hbm.xml files, and when I generate classes with Hibernate Tool I get class property which has primitive type double. I want this property to be java wrapper type Double. How can I achieve this? If I change this manually in my classes, is it going to give any issues to hibernate?
Thanks
I am using "double" in Hibernate .hbm.xml files, and when I generate classes with Hibernate Tool I get class property which has primitive type double. I want this property to be java wrapper type Double. How can I achieve this?
Is the property nullable in the hbm.xml mapping? If it is, you should get a Double.
If you can't change the mapping, you could override the default behavior:
override the column specifically in reveng.xml
use a type-mapping and not-null set to false to handle it for all columns
It only issue you could have is if your property is null amd the column is declared as not null. So I would advise you to always initialize it.
If you can add below statement under type-mapping in your hibernate.reveng.xml ,then you pojos will be generated with double type as java.lang.Double.
<sql-type jdbc-type="DOUBLE" not-null="false" hibernate-type="double" />
Or
if you can add not-null="false" in your hbm files,that also address your issue.
<property name="salary" type="double">
<column name="SALARY" not-null="false" />
</property>

Update one value from a list of dependent objects

Given an entity with a list of components:
class Entity{
Long id;
String name;
List<Component> components = new ArrayList<Component>();
}
class Component{ Object value; }
Configuration:
<hibernate-mapping>
<class name="Entity" table="entity">
<id name="id" access="field" column="id"/>
<property name="name" access="field" unique="true"/>
<list name="components" access="field" table="COMPONENTS" lazy="true">
<key column="id"/>
<list-index column="idx"/>
<composite-element class="Component">
<property name="value" access="field"/>
</composite-element>
</list>
</class>
</hibernate-mapping>
Is it possible to update one component from the list with HQL statement like
update Entity e set e.components[:index].value = :value where e.name = :name
that does not work?
Alternatively, is it possible to configure lazy loading of the list of components in a way that the first access:
entity.components.get(0).value = "..";
does not load the whole list?
Edit:
The lazy="extra" configuration does work for select (loads only the component to update), but it will not update the changed component.
You can't update a single collection element via HQL.
From the 13.4. DML-style operations chapter:
There can only be a single entity named in the from-clause.
No joins, either implicit or explicit, can be specified in a bulk HQL query.
Since your collection element is not an entity, it's not addressable from within bulk update. Technically speaking, non-entity collection elements are not addressable in general; indexed collections or sets with elements having natural ids being the only exceptions.
While it is possible to lazy-load collection elements few at a time (though it doesn't really make sense in this case unless you know ahead of time that you'll only be looking at Nth element since batch size is not easily changeable at runtime), it's not going to help because entire collection will be loaded anyway when you try to update it.
Selecting a single collection element is possible for indexed collection (not part of your question, but I wanted to clarify on this based on KLE answer and your comments):
select c
from Entity e join e.components c
where index(c) = :index

Hibernate Exception help: TransientObjectException

I am getting the following exception when I try to update an object:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: ......
Can anyone help???
The object that I am trying to update has the 'lazy' attribute set to false in the mapping file. Seems like hibernate is expecting me to save child objects before it flushes the update???
EDIT (ADDED):
<hibernate-mapping>
<class name="utils.message.Message" table="messages">
<id name="id" column="message_id">
<generator class="native" />
</id>
<property name="message_text" column="message_text" />
<property name="message_file" column="message_file" />
<property name="is_active" column="is_active" type="boolean"/>
<property name="is_global" column="is_global" type="boolean"/>
<property name="start" column="start" type="java.util.Date"/>
<property name="end" column="end" type="java.util.Date"/>
<property name="last_updated" column="last_updated" type="java.util.Date"/>
<many-to-one name="last_updated_by" class="utils.user.User" column="last_updated_by" lazy="false"/>
<many-to-one name="healthDepartment" class="utils.healthdepartment.HealthDepartment" column="health_department_id" lazy="false"/>
</class>
</hibernate-mapping>
TransientObjectException occurs when you save an object which references another object that is transient (meaning it has the "default" identifier value, frequently null) and then flush the Session. This commonly happens when you are creating an entire graph of new objects but haven't explicitly saved all of them. There are two ways to work around this:
As you suggest, you could use cascading of saves to other associated objects. However, cascading wasn't really intended as a workaround for TOE but rather as a convenience for saving a group of related objects that are frequently manipulated together. If you detach your objects without its full set of associated data and then save it with cascading enabled, you could inadvertently delete data you don't want to lose.
Ensure that all transient objects in your graph are explicitly saved as part of your unit of work. This is really just a case of understanding how your application will be creating an object graph and what entities are transient and which might be persistent or detached.
I would recommend reading this entire chapter from the Hibernate docs to understand fully the terminology of transient, persistent and detached:
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html
dude use property "cascade = true" in mapping. all will well...
V-Boy
With a many-to-one relationship, it would not be appropriate for Hibernate to cascade persistence operations, since the "one" is conceptually an entity shared between many others. This kind of relationship isn't a "child object", as you put it.
You can override this behaviour by explicitly setting the cascade attribute on the relation, or you can manually persist the other end of the many-to-one relations.
App is in a Spring environment. Fix: to run update from within Hibernate environment.

Categories

Resources