Hibernate unsaved-value annotation - java

I would like to force Hibernate (4.2) checking object persistence by the field VERSION instead of the field ID. The xml below should work:
<id name="id" column="ID">
<generator class="assigned" />
</id>
<version name="version" column="VERSION" unsaved-value="null" />
But I want to use annotations. Is this java code enough?
#Id
public String getId() {
return this.id;
}
#Version
public Integer getVersion() {
return this.version;
}
How to specify the unsaved-value tag? I don't find any annotation for this.
I've read somewhere, that Hibernate is smart enough to guess that an object is persistent or not, but it was not too convincing.
And what if I want to use -1 instead of null? There must be a way to achieve this, isn't it?
<version name="version" column="VERSION" unsaved-value="negative" />
Thanks for your help.
Edited. Hibernate 3.6 ref guide says:
"The unsaved-value attribute is almost never needed in Hibernate3 and indeed has no corresponding element in annotations."
and
"The assigned generator makes Hibernate use unsaved-value="undefined". This forces Hibernate to go to the database to determine if an instance is transient or detached, unless there is a version or timestamp property, or you define Interceptor.isUnsaved()."
I belive #Version will be sufficient for me.

Related

Strange behaviour with composite-id and version in hibernate 3.6

I encounter strange behaviour on Hibernate's merge() if I use an entity with a composite-id and a version number.
This is my hibernate mapping file:
<class name="ArticleTurnover" table="T_ARTICLETURNOVER">
<composite-id>
<key-property name="mainArticleId" type="java.lang.Integer" column="ARTICLETURNOVER_ID"/>
<key-property name="locationId" type="java.lang.Integer" column="ARTICLETURNOVER_LOCATIONID"/>
</composite-id>
<version name="version" column="ARTICLETURNOVER_VERSION" />
... some properties
</class>
And this is the code (it fails...):
ArticleTurnover at = new ArticleTurnover();
at.setMainArticleId(1);
at.setLocationId(1);
ArticleTurnover savedAt = em.merge(at);
assertNotNull(savedAt.getMainArticleId());
assertNotNull(savedAt.getLocationId());
After calling merge the fields mainArticleId and locationId are both null. The code above is just a test, but if I would commit a transaction, hibernate would insert null into the composite-id fields, and fail!
If I change em.merge(at) to em.persist(at) everything works. And if I manually set at.setVersion(0) (!!) it also works.
I ended up in adding a component type ArticleTurnoverId for my composite-id like mentioned here: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#d0e4819.
Can anybody tell me what I am doing wrong, or point out why this happens?

Hibernate GUID local generator

I use hibernate to generate ids for my MySQL data-tables:
<class name="XXXX" table="XXXX">
<id name="Id" column="Id" type="string">
<generator class="guid"/>
</id>
....
</class>
it works fine.
however, when i profiling the sql queried, there are 2 sqls for 1 insert:
1).select uuid() and then 2).insert ....
I have 3 questions:
why not hibernate generates the "GUID"s locally?
how much is the overhead for "select uuid()" than "UUID.randomUUID()" for one insert?
can i config a "local" generator in hibernate?
AFAIK the GUID generator is deprecated and you should use the new(er) UUIDGenerator instead. See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#d0e5294.
But to answer your questions
That is how the GUID generator functions it calls the database and the result is passed into the id field of the object
No idea, measure, however I guess the impact is negligible as the only thing you do additionally is return a simply value
Yes but why as it is already supported by Hibernate (see the documentation)

Java DataType mismatch between Oracle and hibernate

My java application is using hibernate with Oracle 10g as the database.
I have landed into an issue and not able to proceed and i need your help here.
Below is the issue that i am facing.
I have a Column in one of my Oracle table which has a datatype of Varchar2(1 byte).
I want to know the proper dataype that i need to use in my pojo class.
Also in the hibernate mapping file what should be the datatype for the same property.
when i am running the file hibernate keeps on giving error like cannot do a conversion.
below are my pojo and .hbm file
public class destination implements Serializable{
private String configId;
private String isCurrent;
//other properties and getter, setters
}
destination.hbm.xml
<class name="com.testing" table="configuration">
<id name="configID" type="java.lang.Integer">
<column name="configuration_id" />
<generator class="identity" />
</id>
<property name="isCurrent" type="Not-SURE">
<column name="is_current" not-null="true" />
</property>
The column i am talking about is the isCurrent property in the pojo and .hbm.xml file.
Its defined as Varchar2(1 byte) in the db. I ma not sure about the datatype and marked it a String but the issue still persists.
I have searched the net but have not got any proper solution for this issue.
Can you please help me here as its really eating my head a lot.
I would focus on the configId you declared it as String in the class but as Integer in the xml.
<id name="configID" type="java.lang.Integer">
Im guessing you want to store current flag on the record. In that case you can do
public class destination implements Serializable{
private String configId;
private boolean current;
public boolean isCurrent() {
return current;
}
}
and hbm mapping like
<property name="current" type="yes_no">
<column name="is_current" not-null="true" />
</property>

Hibernate - One table with multiple entities?

I have a Picture:
public class Picture implements java.io.Serializable {
private byte[] picEncoded;
private String Name;
//etc
Is it's possible to move byte[] to another class without creating physically separated table in db? Do i need to use some inheritance strategy?
edit
Blob in separate entity:
pojo:
public class PictureBlob implements java.io.Serializable {
private Integer pictureBlobId;
private byte[] blob;
hbm::
<class name="PictureBlob" table="PICTURE">
<id name="pictureBlobId" type="int">
<column length="200" name="PictureID"/>
</id>
<property name="blob" type="byte[]" insert="false" update="false">
<column name="PicEncoded" not-null="false"/>
</property>
</class>
Picture:
hbm::
<one-to-one class="PictureBlob" constrained="true" name="pictureBlob" fetch="select"/>
How do i insert new pictures?
PictureBlob pictureBlob= new PictureBlob();
pictureBlob.setBlob(new byte[]{84,32,22});
Picture p = new Picture();
p.setPictureBlob(pictureBlob);
session.save(p);
inserts record where blob value is null.
Is it's possible to move byte[] to another class without creating
physically separated table in db?
Use component mapping which creates a composition relation between Picture and PictureBlob. Example:
<hibernate-mapping>
<class name="Picture" table="PICTURE">
<id name="pictureId" type="int">
<generator class="native" />
</id>
<component name="pictureBlob " class="PictureBlob" lazy="no-proxy">
<property name="pictureBlobId" column="PictureID" type="int" length="200" />
<property name="blob" type="byte[]" insert="false" update="false"column="PicEncoded"/>
</component>
</class>
</hibernate-mapping>
POJO
public class Picture implements java.io.Serializable {
private int pictureId;
private PictureBlob pictureBlob;
//Setters & Getters
}
public class PictureBlob implements java.io.Serializable {
private int pictureBlobId;
private byte[] blob;
//Setters & Getters
}
Also Note:
Use lazy="true" on , and mappings to enable lazy
loading of individual scalar value-typed properties (a somewhat exotic
case). Requires bytecode instrumentation of compiled persistent
classes for the injection of interception code. Can be overriden in
HQL with FETCH ALL PROPERTIES.
Use lazy="no-proxy" on single-valued associations to enable lazy
fetching without the use of a proxy. Requires bytecode instrumentation
for the injection of interception code.
Use lazy="extra" on collections for "smart" collection behavior, i.e.
some collection operations such as size(), contains(), get(), etc. do
not trigger collection initialization. This is only sensible for very
large collections.
See here for more info. on fetching strategies
Edited.
if you interested in using annotations instead of hbm you can take a look at these
http://docs.oracle.com/javaee/6/api/javax/persistence/Embeddable.html, this will exactly solve your purpose.
I think you could use something like this:
<class name="Picture">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<component name="pictureBlob" class="PictureBlob">
<property name="pictureBlobId"/>
<property name="blob"/>
<property name="picture"/>
</component>
</class>
This might need some edititng, but the idea is this:
You have a Picture class. This class has property name and property pictureBlob of type PictureBlob.
the component tag indicates the properties inside the component are mapped to the same table as Picture

How to prevent Hibernate from using 0 as ID?

I am using
#TableGenerator(name="tab",initialValue=2,allocationSize=50)
on Entities and define the ID with
#Id
#GeneratedValue(generator="tab",strategy=GenerationType.TABLE)
private int id;
yet Hibernate still uses 0 as an ID.
I cannot use #GenericGenerator because the annotations do not come with Hibernate4 that ships with Jboss AS7.
Is there a simple solution or do I have to write a custom Generator?
Hibernate is creating ids with id 0 because you have a primitive type. Try using Integer id instead of int id. Remember primitives can't hold a null value.
If you want to generate the custom id generator, you can use a SEQUENCE in DB to generate the id if the object.
<id ....>
<generator class="sequence">
<param name="sequence">YOUR_SEQUENCE _NAME</param>
</generator>
</id>
Read the API about generator classes here.

Categories