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
Related
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.
I have a Hibernate 3 mapping of a table with a medium text field. The table has a few thousands records, other than the medium text field, other fields do not hold much data at all.
The whole table needs to be loaded into memory Except the medium text field, which is very rarely used.
Although I have heard of lazy fetching annotation, however this legacy piece of code is using Hibernate XDoclet, which does not mention lazy fetching in its hibernate property definition:
http://xdoclet.sourceforge.net/xdoclet/tags/hibernate-tags.html##hibernate_property_0_1_
So is there any way to tell Hibernate only to retrieve the value when its getter is called?
Hibernate default supportd lazy fetching unless exlplicity set it to Eager fetching.
If you want to get some idea on lazy fetching refer this
If it is property laza loading try something like
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
>
<class
name="db.hibernateSimple.Copay"
table="EHR_COPAY"
polymorphism="explicit"
>
<id
name="id"
column="COPAY_ID"
type="long"
unsaved-value="null"
>
<generator class="sequence">
<param name="table">HIVAL</param>
<param name="column">NEXT</param>
<!--
To add non XDoclet generator parameters, create a file named
hibernate-generator-params-Copay.xml
containing the additional parameters and place it in your merge dir.
-->
</generator>
</id>
<property
name="balance"
type="int"
column="balance"
length="10"
/>
<property
name="date"
type="java.lang.String"
column="OWNERSHIP_DATE"
/>
<property
name="comments"
type="java.lang.String"
column="comments"
lazy="true"
/>
<many-to-one
name="user"
class="db.hibernateSimple.User"
cascade="none"
outer-join="auto"
column="USER_ID_SEQ"
/>
I extracted the above from here you can get some idea I guess
I tried using lazy=true on the Hibernate property and it does not work, Hibernate still fetches the entire table even when the property is not geted.
As a workaround, I removed the Hibernate property and replaced it by JDBC query in getter, and JDBC statement in setter.
I'm currently working on a Quizzing Tool that uses hibernate and spring. I'm actually building it as a Sakai LMS tool and that complicates this question a little more, but let me see if I can generalize.
My current scenario is when users go to a StartQuiz page, which when they submit the form on the page, initializes an Attempt object(Stored by hibernate). It populates the object below:
<class name="org.quiztool.model.Attempt" table="QT_ATTEMPTS">
<cache usage="transactional" />
<id name="id" type="long">
<generator class="native">
<param name="sequence">QT_ATTEMPTS_ID_SEQ</param>
</generator>
</id>
<many-to-one name="quizId" class="org.quiztool.model.Quiz" cascade="none" />
<property name="score" type="int" not-null="true" />
<property name="outOf" type="int" not-null="true" />
<list name="responses" cascade="none" table="QT_RESPONSES" lazy="false">
<key column="id"/>
<index column="idxr"/>
<many-to-many class="org.quiztool.model.QuizAnswer" />
</list>
<list name="questionList" cascade="none" table="QT_ATTEMPT_QUESTIONS" lazy="false">
<key column="id"/>
<index column="idxq"/>
<many-to-many class="org.quiztool.model.QuizQuestion" />
</list>
<property name="userId" type="string" length="99" />
<property name="siteRole" type="string" length="99" />
<property name="startTime" type="java.util.Date" not-null="true" />
<property name="finishTime" type="java.util.Date" />
</class>
It randomly picks out a set of questions and sets the start time and a few other properties, then redirects the user to the TakeTheQuiz page after saving the object through hibernate.
On the TakeTheQuiz page it loads the attempt object by its ID which is passed as a request param, then prints and formats it into an html form for the user to fill out the quiz. About 2/5 concurrent users will see no questions. The attempt object loads, and its questions are empty.
My theory is that the question list in the Attempt object is either not inserting immediately to the database(which is fine as long as the object goes to the hibernate cache, and I can then get it from the cache ,which I cant see to figure out how to do) OR it is saving to the Database, but my load of the object on the TakeTheQuiz page is reading an incomplete object from the cache.
Admittedly my Hibernate knowledge is limited, so if someone can help me understand what could be happening here and how to fix it, please let me know.
The answer, as I found out, was simple. It seemed that my save function was committing to the database lazily. Once I forced commits for that object at the end of each transaction the problem was solved.
I ended up writing my own hibernate session code which looks like this:
Session session = getSession();
session.beginTransaction();
session.saveOrUpdate(attempt);
session.getTransaction.commit();
session.close();
Problem solved.
My theory is that there is something wrong with the piece of code that randomly picks the questions. Are you sure that it works? Please paste some of your code.
A second theory is that there is something wrong with your transaction boundaries. When do you flush the session? And when is your transaction committed? Give it a try and set the FlushMode on your session to ALWAYS. Does this change something?
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.
I got a pretty simple parent/child relationship here, which looks like this:
Email servers have n folders.
Folders can have n (sub-)folders.
Folders have a reference to their parent folder as well as to the email server they belong to.
My mapping files look like this:
MailServer.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 02.05.2011 12:32:52 by Hibernate Tools 3.3.0.GA -->
<hibernate-mapping>
<class name="test.MailServer" table="MAILSERVER">
<id name="id" type="long" access="field">
<column name="MAIL_SERVER_ID" />
<generator class="native" />
</id>
<bag name="folders" table="FOLDERS" lazy="false" inverse="true" cascade="all-delete-orphan">
<key column="MAIL_SERVER_ID"></key>
<one-to-many class="test.Folder" />
</bag>
</class>
</hibernate-mapping>
Folder.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 04.05.2011 15:02:31 by Hibernate Tools 3.3.0.GA -->
<hibernate-mapping>
<class name="test.Folder" table="FOLDERS">
<id name="id" type="long" access="field">
<column name="FOLDER_ID" />
<generator class="native" />
</id>
<many-to-one name="mailServer" column="MAIL_SERVER_ID" not-null="true" />
<bag name="folders" table="FOLDERS" lazy="false" inverse="true" cascade="all">
<key column="PARENT_FOLDER_ID" not-null="false"></key>
<one-to-many class="test.Folder" />
</bag>
<many-to-one name="parentFolder" column="PARENT_FOLDER_ID" />
</class>
</hibernate-mapping>
The problem I got, is the following.
Let's say, I have the following hierachy:
- MyMailServer
Folder1
- Folder2
Subfolder
Folder3
When I call hibernateSession.save(mailServerInstance); or hibernateSession.update(mailServerInstance);, Hibernate correctly stores everything to the database. The parent column id's are filled correctly. Same for all other references.
BUT when I load the data, Hibernate reloads the folder hierachy like this:
- MyMailServer
Folder1
Folder2
Subfolder
Folder3
I understand the reason: Subfolder has a reference to its MailServer and thus, Hibernate ads it there instead of the folder where it belongs to.
But, how do I solve this problem?
Thanks in advance!
As you already understood what Hibernate does here is logical since you're fetching all folders for given mailServer. I don't think there is a way to achieve what you want in 1 single query (not a hibernate restriction, also with plain old SQL this is not possible).
I have a very similar case where I do the following:
get root folders for mail server (-> where parent folder is null)
for each folder get the child folders
Another solution is using Transfer Objects and you map the entities to the transfer objects so that the required structure is obtained.
It all depends on your use case which (if any) solution is appropriate. E.g. if you can execute an AJAX call each time a folder is expanded (tree structure) then the first solution is ideal.
I worked around this by replacing
<bag name="folders" table="FOLDERS" lazy="false" inverse="true" cascade="all-delete-orphan">
<key column="MAIL_SERVER_ID"></key>
<one-to-many class="test.Folder" />
</bag>
in MailServer.hbm.xml with
<one-to-one name="rootFolder" class="test.Folder" cascade="all" />
That did the trick.