Spring + Hibernate: configuring PK generator? - java

We use Spring + Hibernate for a Webapp.
This Webapp will be deployed on two unrelated production sites. These two production sites will use the Webapp to generate and use Person data in parallel.
What I need to do, is to make sure that the Persons generated on these two unrelated production sites all have distinct PKs, so that we can merge the Person data from these two sites at any time.
A further constraint imposed to me is that these PKs fit in a Long, so I can't use UUIDs.
What I'm trying to do is to change the current hibernate mapping, that has sequence S_PERSON as generator:
<hibernate-mapping default-cascade="save-update" auto-import="false">
<class name="com.some.domain.Person" abstract="true">
<id name="id">
<column name="PERSON_ID"/>
<generator class="sequence">
<param name="sequence">S_PERSON</param>
</generator>
</id>
...
</hibernate-mapping>
into something configurable, so that PERSON_ID have its PKs generated from different sequences (maybe S_PERSON_1 and S_PERSON_2) depending on the deployment site's Spring configuration files.
Of course,
<generator class="sequence">
<param name="sequence">${sequenceName}</param>
</generator>
doesn't work, so I have to figure out something else... I guess my generator should point to a configurable bean that in turn points to a sequence or another, but I can't figure how to do that...
Any ideas or workaround?

You could use sequences on both production systems, but define them differently:
Production System 1:
CREATE SEQUENCE sequence_name START WITH 1 INCREMENT BY 2;
Production System 2:
CREATE SEQUENCE sequence_name START WITH 2 INCREMENT BY 2;
The first sequence will generate only odd numbers, the second only even numbers.

Related

Migrating Hibernate 3 to 5: relation hibernate_sequence does not exist

I am migrating an application running with Hibernate 3 to Hibernate 5.
I have a strange error:
ERROR: relation hibernate_sequence does not exist
We are using *.hbm.xml mapping files and everything was working fine until I changed the Hibernate version. I mean we have a pretty straight forward mapping with ID column and DB sequence generator and still Hibernate wasn't able to pick the correct config.
<hibernate-mapping>
<class name="com.boyan.MyClass" table="my_class">
<id name="id" type="long">
<column name="id" />
<generator class="sequence">
<param name="sequence">my_class_seq</param>
</generator>
</id>
...
</class>
</hibernate-mapping>
I started digging in the Hibernate code and saw that SequenceGenerator is deprecated and the new versions use SequenceStyleGenerator. I was very confused when I noticed that in the new version the property telling which is the sequence name is changed from sequence to sequence_name. So finally when I changed:
<param name="sequence">my_class_seq</param>
to:
<param name="sequence_name">my_class_seq</param>
everything worked.
I bumped in to the same problem and I was using annotations. Solution was the accepted answer JPA GenerationType.AUTO not considering column with auto increment. If using annotations following should be used.
#GenericGenerator(name = "my_seq", strategy = "native", parameters = {
#Parameter(name = "sequence_name", value = "mydb_seq")
})

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)

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.

how to disable generator when db trigger creates id

Currently when I try to insert new records I am getting an error:
[ERROR] 05/12/11_09:44:20.54 [org.hibernate.event.def.AbstractFlushingEventListener] - Could not synchronize database state with session
Db2 triggers to generate the ID need to remain in place to support legacy applications. How can I configure the hbm.xml to not generate the ID?
I'm not sure what version of Hibernate you are using, but Hibernate currently supports getting an ID that is generated from trigger via a special generator called select.
In short, you can add this generator to your ID column, and then reference a natural key you can use to retrieve the trigger generated ID as follows:
<id name="id" type="long" column="person_id">
<generator class="select">
<param name="key">socialSecurityNumber</param>
</generator>
</id>
If your mapping already has a natural-key entry defined, then you shouldn't even need to specify the key param to the generator.
One problem with this particular generator is that you can only use one entity property as the selection key for it. If you need to select via a composite key, then you'll have to create your own generator for this purpose.
You could extend org.hibernate.id.SelectGenerator or one of it's parents, and then implement the select via multiple columns that way. Then you simply replace the class attribute of the above generator entry with the fully qualified class name of your new generator.

Hibernate's generator class not really working?

Asking this question here after hours of frustration with me and my Eclipse. Hoping to find some respite here.
I'm trying to save a pojo object into MySQL database via Hibernate 3.0. Basically my requirement is: I need to assign the id for the object before save and not let Hibernate do it for me.
For this I looked up in the documentation and saw that <generator class="assigned"/> perfectly fits my bill. Consequently I updated by .hbm.xml file with the following for the id:
<id name="id" type="int">
<column name="ID" />
<generator class="assigned" />
</id>
My pojo matches .hbm.xml file to the T.
I'm setting all the parameters including the ID of my pojo and calling Hibernate's saveOrUpdate(object) method.
If it's of any help, the ID column of my database table has "auto-inc" disabled.
Unbelievably, when I look at the database table contents, a row has been inserted with Hibernate's own ID and not what I had set.
How's it possible? Is there anything else affecting the ID? Am I missing on something? What's the work around?
My hibernate.properties looks like below(if it's of any help):
hibernate.connection.driver_class =com.mysql.jdbc.Driver
hibernate.dialect =org.hibernate.dialect.MySQLDialect
hibernate.connection.url =jdbc:mysql://localhost/dbdbdbdbdb
hibernate.connection.username=root
hibernate.connection.password=password
hibernate.connection.pool_size=10
jdbc.batch_size=30
hibernate.show_sql=true
hibernate.current_session_context_class=true
hibernate.hbm2ddl.auto=validate
hibernate.cglib.use_reflection_optimizer=false
hibernate.generate_statistics=true
hibernate.cache.use_query_cache=true
hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.EhCacheRegionFactory
Well, hoax alarm!. It was really an issue with Eclipse-Tomcat integration. I had to clean up Tomcat's directories and republish before the hbm files could take effect.
Tip: If you run ant within Eclipse, be sure to keep refreshing Eclipse workspace every now and then. Learning some things the hard way.
You can write your custom sequence generator class to return ids suitable to your requirement. For more details follow: http://danu-javastuff.blogspot.com/2009/01/custom-id-generator-class-for-hibernate.html

Categories