Error generating sequence in HSQLDB with Hibernate using hbm2ddl - java

I am getting an error while generating a sequence for an id field in HSQLDB. The mapping file is configurated like this:
<hibernate-mapping>
<class name="ddol.rtdb.dto.Configuration" table="RTDB_CONFIGURATION">
<id name="id" type="int">
<column name="CONF_ID" />
<generator class="sequence">
<param name="sequence">CONF_ID_SEQ</param>
</generator>
</id>
<property generated="never" lazy="false" name="configurationDate"
type="java.util.Date">
<column name="CONF_DATE" />
</property>
It works when I use the same mapping with oracle, but does not generate the sequence when used with HSQLDB for testing. Is there anything else I should add to the mapping?
The error I am getting when I try to insert something into the table is:
ERROR org.hibernate.util.JDBCExceptionReporter - user has no privileges or object not found: CONF_ID_SEQ
HSQLDB version is 2.2.8, Hibernate version is 3.6.10

Create the sequence(CONF_ID_SEQ - if it doesn't exists) and make sure that you have "grant" permission for that.
Alternatively, you can create a "synonym" for the sequence and give "grant" permission for all the users or to the specific users you want to. Then it should work.
E.g
Consider, You are creating Sequence as "dbauser". Now, some other "user"(who don't have access) trying to use it,
then u will get "user has no privileges" error.
In that case you can use above strategy.

Related

getting invalid mapping exception when setting lazy=true in hibernate java

I want to use lazy="true" in hibernate while loading detail using Jersey in JAVA. But I getting error. (hbm version 5.1.3.Final)
Here is my code:
<class name="com.icaube.application.prac.details.PracAccountDetail" table="prac_account_master">
<id column="account_id" name="accountId">
<generator class="com.icube.platform.IdGenerator">
<param name="componentName">PracAccount</param>
</generator>
</id>
//here lazy=true
<many-to-one name="pracRankDetail" class="com.icaube.application.prac.details.PracRankDetail" column="rank_id" lazy="true"/>
<one-to-one name="pracAddressDetail" property-ref="accountId" lazy="false" />
<property column="name" name="name" not-null="true" unique="false"/>
<property column="rank_id" name="rankId" not-null="true" unique="false"/>
</class>
Getting ERROR:
Initial SessionFactory creation failed.org.hibernate.boot.InvalidMappingEelloxception: Could not parse mapping document: PracComponents.hbm.xml (RESOURCE)
What is wrong in this? How can I make it correct?
Thanks :-)
you class tag
<class name="com.icaube.application.prac.details.PracAccountDetail" table="prac_account_master">
is not being closed or you did not post everything in your xml file.
The error Could not parse mapping document is about your xml files not being well-formed. When this error comes up, we'd better double check our xml files to see if they are really OK (all tags are properly closed and so on).
To know more refer below links :
org.hibernate.InvalidMappingException: Could not parse mapping document from resource *.hbm.xml
https://coderanch.com/t/217940/databases/Hibernate-InvalidMappingException-parse-mapping-document

How to migrate same class with 2 entity-names to Spring Data JPA?

I am migrating an app to Spring Data JPA from Hibernate. I already migrated a few repositories and have that working. I now have a special case I need to convert.
I have this in my .hbm.xml:
<class name="SoundNotification" table="SoundNotification" entity-name="SoundNotificationWithData">
<id name="m_id" type="int" column="id" unsaved-value="-1">
<generator class="native"/>
</id>
<property name="m_name" column="name" unique="true" not-null="true"/>
<property name="m_data" column="data"
type="com.traficon.tmsng.server.common.service.persistence.impl.hibernate.usertype.BlobUserType"
not-null="true"/>
<property name="m_size" formula="OCTET_LENGTH(data)"/>
<property name="m_inUse"
formula="(select count(1) from EventTypeConfiguration etc where etc.soundNotification=id)"/>
</class>
<class name="SoundNotification" table="SoundNotification" entity-name="SoundNotificationWithoutData">
<id name="m_id" type="int" column="id" unsaved-value="-1">
<generator class="native"/>
</id>
<property name="m_name" column="name" unique="true" not-null="true"/>
<property name="m_size" formula="OCTET_LENGTH(data)"/>
<property name="m_inUse"
formula="(select count(1) from EventTypeConfiguration etc where etc.soundNotification=id)"/>
</class>
Notice how I only have 1 class SoundNotification, but it is used with 2 different entity-names (SoundNotificationWithData and SoundNotificationWithoutData)
Is it possible to convert this to Spring Data JPA? Would I need to create 2 java classes as a "workaround" ?
Another example which we have is this one:
<class name="FlowDataMessageImpl" entity-name="FlowDataPer10s" table="FlowDataPer10s">
...
</class>
<class name="FlowDataMessageImpl" entity-name="FlowDataPer20s" table="FlowDataPer20s">
....
</class>
<class name="FlowDataMessageImpl" entity-name="FlowDataPer2m" table="FlowDataPer2m">
...
</class>
Here we store the same "Java object" in different tables after we did some roll-up calculations. I would like to map this using JPA (or somebody to tell me it is a bad idea and I should use Hibernate directly like before for this)
To your first question: you will have to create two Java classes SoundNotificationWithoutData and SoundNotificationWithData, both classes extending the same third Java class, using the #Inheritance(strategy=InheritanceType.SINGLE_TABLE) and mapped with the #Table(name="SoundNotification") annotation. Also notice that you will not be able in plain JPA to create a property with a formula (property m_inUse), so you will have to use Hibernate-specific stuff OR load that property only when you need it.
To your second problem: again, either use Hibernate-specific stuff, OR use the #MappedSuperclass annotation on the superclass (which is extended by every FlowDataPer* classes), without using on it the #Entity and #Inheritance annotations. Of course you could also use the same solution as for your first question: different classes (FlowDataPer10s, FlowDataPer20s, ..) extending a base entity class, anntoated with #Entity and #Inheritance(strategy=InheritanceType.TABLE_PER_CLASS), but I find it more elegant with the #MappedSuperclass annotation.

Hibernate 4 composite-id NonUniqueObjectException

I have NonUniqueObjectException thrown when upgrading my project from Hibernate 3 to Hibernate 4.
I created minimal Hibernate 4 project for testing purposes, and managed to reproduce this exception by:
having entity House, and another entity Door that has a composite id that contains House entity
<class dynamic-insert="true" dynamic-update="true" name="entity.Door" select-before-update="true" table="DOOR">
<composite-id name="id" class="DoorHousePK">
<key-many-to-one class="entity.House" column="HOUSEID" name="house"/>
<key-property column="DOORID" name="doorId" type="string"/>
</composite-id>
and then in the same transaction fetching a House and then fetching Door by composite id with:
(Door)session.get(Door.class, doorHousePK)
Here is the hbm file for House:
<class dynamic-insert="true" dynamic-update="true" name="entity.House" select-before-update="true" table="HOUSE">
<id column="ID" name="id" type="int"/>
<property column="squarefeet" name="squareFeet" not-null="false" type="int"/>
<property column="address" length="255" name="address" not-null="false" type="string"/>
<property column="color" length="32" name="color" not-null="false" type="string"/>
<property column="description" name="description" not-null="false" type="materialized_clob"/>
</class>
,and the stack trace of the error:
INFO: HHH000327: Error performing load command : org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [entity.House#1]
Exception in thread "main" org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [entity.House#1]
at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:617)
at org.hibernate.event.internal.AbstractReassociateEventListener.reassociate(AbstractReassociateEventListener.java:74)
at org.hibernate.event.internal.DefaultLockEventListener.onLock(DefaultLockEventListener.java:95)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:774)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:767)
at org.hibernate.internal.SessionImpl.access$1800(SessionImpl.java:176)
at org.hibernate.internal.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2491)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.addKeyManyToOnesToSession(EntityLoadQueryDetails.java:263)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:247)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:129)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4126)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:503)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:468)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:213)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:275)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070)
at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:176)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2551)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:955)
When reverting this minimal project back to Hibernate 3 the exception is gone, and it all works fine.
What is the difference in composite-id handling between Hibernate 3 and Hibernate 4?
How can I make this work in Hibernate 4?
I recently migrated from hibernate 3 to 4 with two tables with composite ids and related to each other by composite foreign key. Exactly same configuration worked fine in both versions. So there is no difference as far as basic concepts about composite-id functionality are concerned.
You should enable debugging for hibernate APIs i.e. set debug level for org.hibernate.* to DEBUG in log properties file to see which SQLs are being fired. That will help you see if any additional/unexpected SQLs are being fired by hibernate.
Make sure your entities, and the objects that make up your composite primary key, have appropriate implementations of hashCode() and equals(). I seem to remember there being some underlying changes in hash-code usage and/or object equality checking between Hibernate 3 and 4.

Map hibernate many-to-one with the foreign key in subclass joined table

I'm mapping some entities using Hibernate 3 for my project and simply explained I've got kind of this:
Student entity (tstudent table)
UniversityStudent entity (tuniversitystudent table)
University entity (tuniversity table)
UniversityStudent extends from Student and has its own attributes, like the university itself, which is a foreign key into the tuniversitystudent table. It is also mapped like a subclass into the Student class, using a discriminator field:
<class name="mycompany.Student" table="tstudent" discriminator-value="BASIC">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<discriminator column="type" />
<property name="name" column="name" />
<property name="surname" column="surname" />
<property name="phoneNumber" column="phone_number" />
<subclass discriminator-value="UNIVERSITY"
name="mycompany.UniversityStudent">
<join table="tuniversitystudent">
<key column="id_student" />
<many-to-one name="university" class="mycompany.University">
<column name="id_university" />
</many-to-one>
</join>
</subclass>
</class>
Well, now I want to have a Set collection with the UniversityStudent entities for each University. So I map it like that:
<class name="mycompany.University" table="tuniversity">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<property name="name" column="name" />
<set name="universityStudents" table="tuniversitystudent">
<key>
<column name="id_university" />
</key>
<one-to-many class="mycompany.UniversityStudent" />
</set>
</class>
My problem comes when I want to load a University object, Hibernate complains that id_university doesn't exist in tstudent table. I checked the generated SQL query and it really tries to load it from tstudent.
Unknown column 'student0_.id_university' in 'field list'
It seems that it's recognizing that it is a subclass of the basic Student and tries to join the collection using a field in the parent table, but however the field is actually in the child table, because only university students can have a University assigned.
I tried another workaround which seems to work but it's not valid for me, that's mapping the UniversityStudent as a joined-subclass instead of a subclass with a join inside:
<joined-subclass name="mycompany.UniversityStudent" table="tuniversitystudent">
<key column="id_student" />
<many-to-one name="university" class="mycompany.University">
<column name="id_university" />
</many-to-one>
</joined-subclass>
However, I'm interested in keeping it as a subclass with a discriminator value. Any idea?
I checked out some resources and finally got into this bug: https://hibernate.atlassian.net/browse/HHH-1015, which looks absolutely compatible with your case. Checkout this old question as well, again very similar to your case.
I firstly read the definition of table per sublass given by Hibernate (I know, it is for version 3.3 but I couldn't find the same source for Hibernate 4): joined-subclass seems (to me) to be a custom implementation of subclass using a discriminator provided by Hibernate and that is a good reason to stay away from its usage. However, from what I know, the mappings table per sublass and table per subclass using a discriminator should be equivalent, that's why I believe the bug I pointed you out is really still open.
If you have time and will, you can try to use another JPA provider and check if you still run in the same issue. JPA 2.0 specifications is a thing, provider implementation is another! I recently run into another bug (related to #IdClass) which forced me to try EclipseLink and the configuration which was not working with Hibernate was right with Eclipse Link
Seems you can use Custom SQL (or HQL) for loading. Haven't tried it myself, but looks like, hmm, at least as a last resort, it provides a decent solution.
Define the query in your HBM:
<sql-query name="universityStudents">
<load-collection alias="unistu" role="University.universityStudents"/>
SELECT unistu.*, student.*
FROM tuniversitystudent unistu
JOIN tstudent student
ON unistu.id_student = student.id
WHERE unistu.id_university = :id
</sql-query>
And then use it inside University:
<set name="universityStudents" inverse="true">
<key/>
<one-to-many class="mycompany.UniversityStudent"/>
<loader query-ref="universityStudents"/>
</set>

How to Stop Hibernate From Trying to Update one-to-many Over Join Table

Ok so I'm having bit of a problem with my Hibernate mappings and getting the desired behavior.
Basically what I have is the following Hibernate mapping:
<hibernate-mapping>
<class name="com.package.Person" table="PERSON" schema="MYSCHEMA" lazy="false">
<id name="personId" column="PERSON_ID" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">PERSON_ID_SEQ</param>
</generator>
</id>
<property name="firstName" type="string" column="FIRST_NAME">
<property name="lastName" type="string" column="LAST_NAME">
<property name="age" type="int" column="AGE">
<set name="skills" table="PERSON_SKILL" cascade="all-delete-orphan">
<key>
<column name="PERSON_ID" precision="12" scale="0" not-null="true"/>
</key>
<many-to-many column="SKILL_ID" unique="true" class="com.package.Skill"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.package.Skill" table="SKILL" schema="MYSCHEMA">
<id name="skillId" column="SKILL_ID" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">SKILL_ID_SEQ</param>
</generator>
</id>
<property name="description" type="string" column="DESCRIPTION">
</class>
</hibernate-mapping>
So lets assume that I have already populated the Skill table with some skills in it. Now when I create a new Person I want to associate them with a set of skills that already exist in the skill table by just setting the ID of the skill. For example:
Person p = new Person();
p.setFirstName("John");
p.setLastName("Doe");
p.setAge(55);
//Skill with id=2 is already in the skill table
Skill s = new Skill()
s.setSkillId(2L);
p.setSkills(new HashSet<Skill>(Arrays.asList(s)));
PersonDao.saveOrUpdate(p);
If I try to do that however I get an error saying:
WARN (org.slf4j.impl.JCLLoggerAdapter:357) - SQL Error: 1407, SQLState: 72000
ERROR (org.slf4j.impl.JCLLoggerAdapter:454) - ORA-01407: cannot update ("MYSCHEMA"."SKILL"."DESCRIPTION") to NULL
ERROR (org.slf4j.impl.JCLLoggerAdapter:532) - Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
The reason I am getting this error I think is because Hibernate sees that the Skill with Id 2 has 'updated' its description to null (since I never set it) and tries to update it. But I don't want Hibernate to update this. What I want it to do is insert the new Person p and insert a record into the join table, PERSON_SKILL, that matches p with the skill in the SKILL table with id=2 without touching the SKILL table.
Is there anyway to achieve this behavior?
Instead of creating the Skill object yourself:
//Skill with id=2 is already in the skill table
Skill s = new Skill()
s.setSkillId(2L);
p.setSkills(new HashSet<Skill>(Arrays.asList(s)));
You should be retrieving it from the Hibernate Session:
Skill s = (Skill) session.get(Skill.class, 2L);
p.setSkills(new HashSet<Skill>(Arrays.asList(s)));
This way the Session thinks that the skill contained in p.skills is persistent, and not transient.
This may be possible if you don't cascade all-delete-orphan which is explicitely telling hibernate to cascade the changes.
But the right way would be IMO to load load the desired Skill entity from the database and to add it to the set of skills of the Person.

Categories