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.
Related
I am new to Hibernate and question is "Is Generator class need for ID tag in Hibernate?"
In my table have trigger mentioned below and my table is existing table and having records.Just I did code change from Native SQL to Hibernate session. in this case "Is Generator class need for ID tag in Hibernate? or not" . Here my exception is record need to insert with next sequence value.
TRIGGER TRG_BI_APPLICATION_DATA_LOCK
BEFORE INSERT
ON APPLICATION_DATA_LOCK REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
exception_no_null_pk EXCEPTION;
BEGIN
IF :new.APP_DATA_LOCK_ID is null
THEN
SELECT SEQ_APPLICATION_DATA_LOCK_PK.nextval
INTO :new.APP_DATA_LOCK_ID
FROM dual;
END IF;
END;
Assuming before insert call trigger will create next ID value and insert will happen. So, in hbm file, we need generator class or if we need means which generator have to use?
Please help me in this regard...
Thanks...
I'm going to infer what you are asking from your question title and the answer to that is no, you don't need a #GeneratedValue annotation for your ID to work, only if you want to specify that a) your ID is going to be a value not generated by Hibernate, and b) if you want to specify how your ID is going to be generated.
I think what you need to do is this:
#Entity
#Table
public class Foo{
#Id
#GeneratedValue(generator = "applicationLockSequence")
#SequenceGenerator(name = "applicationLockSequence" sequenceName = "SEQ_APPLICATION_DATA_LOCK_PK")
private int id;
....
}
This basically specifies that there is a sequence on the database with that name, and that Hibernate should use that sequence to assign your object an ID when it gets saved. There is no need to do this at a database level with a trigger, although that is also a valid method. If you want to do it with a trigger, just leave out #GeneratedValue and #SequenceGenerator.
Hope that answers your question.
TL;DR OP is using a .hbm file for hibernate mappings.
As given here: How To Use Sequence In Hibernate As A Property In XML Mapping
<id name="id" column="item_id>
<generator class="sequence">
<param name="sequence">SEQ_APPLICATION_DATA_LOCK_PK</param>
</generator>
</id>
should be all you need to do this.
I'm getting the following error message from hibernate when attempting to insert a row into a table:
org.hibernate.exception.ConstraintViolationException: Column
'priority' cannot be null
I know that I could put a line into the code to set the value but there are many other instances where the program relies on the default value in the database (db is mysql).
I read somewhere that you can provide a default value in the hbm.xml file but hibernate is not recognizing it. Here's the corresponding section from JobQueue.hbm.xml
<property name="priority" type="integer">
<column name="priority" default="0" />
</property>
I suppose another option would be to modify the JobQueue.java file that gets generated (I'm using eclipse hibernate tools to auto generate the hibernate classes) but for now I'd like to try to get the hbm.xml configuration to work.
I'm using version 4.1.3 of the hibernate libraries and eclipse hibernate tools 3.4.0.x.
default="0" is only relevant for SchemaExport which generates the database schema. other than that hibernate completely ignores this setting. you could try to set not-null="true" for the column.
Unless you are not able to recreate the whole database schema, you can set the default value in the variable initialization.
In your model set the priority to 0 in the initialization.
In your class:
private Integer priority = 0;
I ended up modifying the JobQueue.java POJO to set the default value. To make sure that the Code Generation of hibernate tools wouldn't overwrite this change, I set it up so that the code generation generates the files in a temp folder and then the necessary files are copied over to the permanent source location.
I am trying to map a class Language to a class User.
Many to one mapping is working fine, and through the functionality of the app I can set the value from it's default of null to a particular value.
The problem is that I'd like to set the default mapping to idLanguage 1, but when it maps everything is set to null.
I have tried:
< many-to-one name="language" class="com. \etc\ .language.Language" column="language" default="1" lazy="false" />
However that gives me an error "Attribute default must be declared for element type Many To One.
What to do?
(note: language is mapped to language object in user class, rather than a language id. Setting in the app puts the id of the language in the language column, replacing null value)
I hope the languages will be seed data in your application. Then have a separate langId field in the User mapping and set it to 1. The Object mapping can be used while loading the User bean.So modify the mapping as below.
< many-to-one name="language" class="com. \etc\ .language.Language" column="language" lazy="false" insert="false" update="false"/>
<property name="langId" column="language"/>
This way it will be more performative as you don't have to fetch the Languages bean from the DB before you save the User bean. Also on load of User the languages will be available to.
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.
I have two objects:
public class ParentObject {
// some basic bean info
}
public class ChildObject extends ParentObject {
// more bean info
}
Each of these tables corresponds to a differnet table in a database. I am using Hibernate to query the ChildObject, which will in turn populate the parent objects values.
I have defined my mapping file as so:
<hibernate-mapping>
<class name="ParentObject"
table="PARENT_OBJECT">
<id name="id"
column="parent"id">
<generator class="assigned"/>
</id>
<property name="beaninfo"/>
<!-- more properties -->
<joined-subclass name="ChildObject" table="CHILD_OBJECT">
<key column="CHILD_ID"/>
<!--properties again-->
</joined-subclass>
</class>
</hibernate-mapping>
I can use hibernate to query the two tables without issue.
I use
session.createQuery("from ChildObject as child ");
This is all basic hibernate stuff. However, the part which I am having issues with is that I need to apply locks to the all the tables in the query.
I can set the lock type for the child object by using the query.setLockType("child", LockMode.?). However, I cannot seem to find a way to place a lock on the parent table.
I am new to Hibernate, and am still working around a few mental roadblocks. The question is: how can I place a lock on the parent table?
I was wondering if there was a way around having to do this without undoing the Polymorphic structure that I have set up.
Why do you have to lock both tables? I'm asking because depending on what you're trying to do there may be alternative solutions to achieve what you want.
The way things are, Hibernate normally only locks the root table unless you're using some exotic database / dialect. So, chances are you're already locking your ParentObject table rather than ChildObject.
Update (based on comment):
Since you are using an exotic database :-) which doesn't support FOR UPDATE syntax, Hibernate is locking the "primary" tables as they are specified in query ("primary" in this case being table mapped for the entity listed in FROM clause, not the root of the hierarchy - e.g. ChildObject, not ParentObject). Since you want to lock both tables, I'd suggest you try one of the following:
Call session.lock() on entities after you've obtained them from the query. This should lock the root table of the hierarchy, however I'm not 100% sure on whether it'll work because technically you're trying to "upgrade" the lock that's already being held on a given entity.
Try to cheat by explicitly naming ParentObject table in your query and requesting lock mode for it:
String hql = "select c from ChildObject c, ParentObject p where c.id = p.id";
session.createQuery(hql)
.setLockMode("c", LockMode.READ)
.setLockMode("p", LockMode.READ).list();