Java Hibernate Mapping File not working - java

The error I get is " org.hibernate.MappingException: Repeated column in mapping for entity: cdd.model.Answer column: answer_id (should be mapped with insert="false" update="false") ". However when I put those as attributes I get the error: "Attribute "insert" must be declared for element type "id"."
Any help would be appreciated.
Class:
public class Answer {
UUID answerID;
String content;
//constructors and getters and setters
}
Table:
CREATE TABLE IF NOT EXISTS answer (
answer_id uuid NOT NULL ,
content text NOT NULL,
primary key(answer_id)
);
Hibernate Mapping File:
<!-->==== Answer ====<!-->
<class name="cdd.model.Answer" table="answer" >
<id column="answer_id" name="answerID"
type="org.hibernate.type.PostgresUUIDType"
insert="false" update="false">
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
<property column="content" name="content" type="org.hibernate.type.TextType"/>
</class>
Note
I have a Question class where a question has a set of answers. This is the mapping I used. I am posting it because the error I'm gettng may be because of how I mapped this one-to-many relationship (I'm not sure).
<!-- ==== Question ==== -->
<class name="cdd.model.Question" table="question">
<id column="question_id" name="questionID" type="org.hibernate.type.PostgresUUIDType">
< generator class="org.hibernate.id.UUIDGenerator"/>
</id>
<many-to-one column="submitted_by" name="submittedBy" not-null="true"/>
<many-to-one column="parentCategory" name="parentCategory" not-null="true"/>
<property column="title" name="title" type="org.hibernate.type.TextType"/>
<property column="correct_answer" name="correctAnswer" type="org.hibernate.type.TextType"/>
<property column="date_submitted" name="dateSubmitted" type="org.hibernate.type.TimestampType"/>
<set cascade="all" name="answers" table="answer">
<key column="answer_id" not-null="true"/>
<one-to-many class="cdd.model.Answer"/>
</set>
<join inverse="true" optional="true" table="category_questions">
<key column="question_id"/>
</join>
<join inverse="true" optional="true" table="accepted_questions_by_user">
<key column="question_id"/>
</join>
</class>

Question Entity:
<id column="question_id" name="questionID" type="org.hibernate.type.PostgresUUIDType">
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
Answer Entity:
<id column="answer_id" name="answerID" type="org.hibernate.type.PostgresUUIDType"
insert="false" update="false">
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
remove insert="false" update="false" from Answr entity
should look someting like this
<id column="answer_id" name="answerID" type="org.hibernate.type.PostgresUUIDType" >
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
update, insert (optional - defaults to true): specifies that the mapped columns should be included in SQL UPDATE and/or INSERT statements. Setting both to false allows a pure "derived" property whose value is initialized from some other property that maps to the same column(s), or by a trigger or other application.

Related

A different object with the same identifier value was already associated with the session, even when evicting the objects

I am using Hibernate 5.6 and have user Profile with Groups, which have Columns, which have ColumnProperties. I'd like to clone a column of a profile and attach it to the column group.
Profile -> Groups -> Columns -> ColumnProperties
I get this error:
10:58:39,793 ERROR
[com.myApp.core.rmgt.profile.service.RmgtProfileServiceImpl] (default
task-2) javax.persistence.EntityExistsException: A different object
with the same identifier value was already associated with the session
:
[com.myApp.core.rmgt.profile.business.object.RmgtColumnPropertyBVOImpl#124320]
Here's my mapping files:
<hibernate-mapping>
<class name="com.myapp.core.rmgt.profile.business.object.RmgtProfileBVOImpl" table="rmgt_t_profile" proxy="com.myapp.core.rmgt.profile.common.business.object.RmgtProfileBVO">
<id name="rowguid" column="rowguid" type="java.lang.Long">
<generator class="sequence">
<param name="sequence_name">rmgt_t_profile_rowguid_seq</param>
</generator>
</id>
...
<set name="groups" table="rmgt_t_group" lazy="false" cascade="all-delete-orphan" order-by="rmgtg_group_order asc">
<key column="rmgtg_fk_profile_id" not-null="true"/>
<one-to-many class="com.myapp.core.rmgt.profile.business.object.RmgtGroupBVOImpl"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.myapp.core.rmgt.profile.business.object.RmgtGroupBVOImpl" table="rmgt_t_group" proxy="com.myapp.core.rmgt.profile.common.business.object.RmgtGroupBVO">
<id name="rowguid" column="rowguid" type="java.lang.Long">
<generator class="sequence">
<param name="sequence_name">rmgt_t_group_rowguid_seq</param>
</generator>
</id>
...
<set name="columns" table="rmgt_t_column" lazy="false" cascade="all-delete-orphan" order-by="rmgtc_column_order asc">
<key column="rmgtc_fk_group_id" not-null="true"/>
<one-to-many class="com.myapp.core.rmgt.profile.business.object.RmgtColumnBVOImpl"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.myapp.core.rmgt.profile.business.object.RmgtColumnBVOImpl" table="rmgt_t_column" proxy="com.myapp.core.rmgt.profile.common.business.object.RmgtColumnBVO">
<id name="rowguid" column="rowguid" type="java.lang.Long">
<generator class="sequence">
<param name="sequence_name">rmgt_t_column_rowguid_seq</param>
</generator>
</id>
...
<set name="columnProperties" table="rmgt_t_column_property" lazy="false" cascade="all-delete-orphan" order-by="rmgtcp_order asc">
<key column="rmgtcp_fk_column_id" not-null="true"/>
<one-to-many class="com.myapp.core.rmgt.profile.business.object.RmgtColumnPropertyBVOImpl"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.myapp.core.rmgt.profile.business.object.RmgtColumnPropertyBVOImpl" table="rmgt_t_column_property" proxy="com.myapp.core.rmgt.profile.common.business.object.RmgtColumnPropertyBVO">
<id name="rowguid" column="rowguid" type="java.lang.Long">
<generator class="sequence">
<param name="sequence_name">rmgt_t_column_property_rowguid_seq</param>
</generator>
</id>
<property name="key" type="java.lang.String" column="rmgtcp_key" not-null="true" />
<property name="value" type="java.lang.String" column="rmgtcp_value" not-null="true" />
<property name="order" type="java.lang.Integer" column="rmgtcp_order" not-null="true" />
</class>
</hibernate-mapping>
What I do is i fetch a Profile from DB, then I use Spring's BeanUtils.copyProperties() to create a copy of the column that I want to clone. I made sure to evict all columnProperties before I proceed.
RmgtColumnBVO column = columnService.findLazyById(columnId);
// Evict all properties to force hibernate write new instances to DB
column.getColumnProperties().stream().forEach(x -> profileDAO.getSession().evict(x));
RmgtColumnBVO columnClone = new RmgtColumnBVOImpl();
BeanUtils.copyProperties(column, columnClone);
columnClone.setRowguid(null);
columnClone.setProfileId(profileId);
columnClone.setGroupId(groupId);
Then I null all rowguids of columnProperties objects of the columnClone:
// clone properties
Set<RmgtColumnPropertyBVO> propertys = column.getColumnProperties();
Set<RmgtColumnPropertyBVO> propertysClone = new HashSet<RmgtColumnPropertyBVO>();
for (RmgtColumnPropertyBVO property : propertys) {
RmgtColumnPropertyBVO propertyClone = new RmgtColumnPropertyBVOImpl();
BeanUtils.copyProperties(property, propertyClone);
propertyClone.setRowguid(null);
propertysClone.add(propertyClone);
}
columnClone.setColumnProperties(propertysClone);
After that, I fetch the profile and attach the cloned column to it and save the profile again:
RmgtProfileBVO profile = profileService.findById(column.getProfileId());
profile.getGroup(groupId).getColumns().add(columnClone);
profileService.saveOrUpdate(profile, object.getCreationUser());
What can I do to fix the problem? I don't understand why Hibernate is still complaining about the properties when I evicted every original one.
I found a solution for my problem. I replaced the profileService.saveOrUpdate() with profileService.merge() which did the job (although I do not fully understand why saveOrUpdate() does not).
In my opinion, saveOrUpdate should
Check if profile exists and check if there are changes (new elements in collections, new attribute values).
Check for every mapped collection (in my case: columns) if there are attribute changes or new items
Traverse the mapping tree and check for every mapped collection (columnProperties) of a mapped collection (columns) if value changes or new items (which was the case for me) and update/insert accordingly.

Difficulties on mapping many-to-many relation with extra column with hibernate XML mapping

I am developing a e-shopping program with the help of hibernate. Because I am a very fresh beginner on jsp, servlet, hibernate, I don't know how to do many-to-many relation mapping with additional column in the relation table. I have read through several tutorial but most of them are focus on the annotation mapping and the documentation on hibernate community but none of them suit my situation.
I have three tables movie_information, order_ and order_details(the relationship) where the structure of order_details is as the following.
order_details
-------------
order_id FK
movie_id FK
quantity
-------------
I am trying to use four POJO classes to achieve the many-to-many relation. Here comes the code.
MovieInformation.java
// other variable, constructor, getter, setter
private Set<OrderDetails> orderDetails = new HashSet<OrderDetails>();
Order.java
// other variable, constructor, getter, setter
private Set<OrderDetails> orderDetails = new HashSet<OrderDetails>();
OrderDetails.java
private OrderDetailsPK primaryKey;
private Order order;
private MovieInformation movie;
private int quantity;
OrderDetailsPK.java
private long orderId;
private long movieId;
MovieInformation.hbm.xml
<id column="movie_id" name="movieId" type="long">
<generator class="native"/>
</id>
// some property
<set name="orderDetails" table="order_details" inverse="true" lazy="true" fetch="select">
<key>
<column name="movie_id" not-null="true" />
</key>
<one-to-many class="cart.hibernate.orderDetails.orderDetails" />
</set>
Order.hbm.xml
<id column="order_id" name="orderId" type="long">
<generator class="native"/>
</id>
//some properties
<set name="orderDetails" table="order_details" inverse="true" lazy="true" fetch="select">
<key>
<column name="order_id" not-null="true" />
</key>
<one-to-many class="cart.hibernate.orderDetails.orderDetails" />
</set>
OrderDetails.hbm.xml
<composite-id name="orderDetailsPK" class="cart.hibernate.orderDetailsPK.OrderDetailsPK">
<key-property column="order_id" name="orderId" type="long"/>
<key-property column="movie_id" name="movieId" type="long"/>
</composite-id>
<many-to-one name="order" class="cart.hibernate.order.Order" insert="false" update="false"/>
<many-to-one name="movie" class="cart.hibernate.movieInformation.MovieInformation" insert="false" update="false"/>
<property column="quantity" name="quantity" type="int"/>
OrderDetailsPK.hbm.xml
<class name="cart.hibernate.orderDetailsPK.OrderDetailsPK" >
<property name="orderId" type="long"/>
<property name="movieId" type="long"/>
hibernate.cfg.cml
<mapping class="cart.hibernate.MovieInformation" package="cart.hibernate.movieInformation" resource="cart/hibernate/movieInformation/MovieInformation.hbm.xml"/>
<mapping class="cart.hibernate.Order" package="cart.hibernate.order" resource="cart/hibernate/order/Order.hbm.xml"/>
<mapping class="cart.hibernate.OrderDetails" package="cart.hibernate.orderDetails" resource="cart/hibernate/orderDetails/OrderDetails.hbm.xml"/>
<mapping class="cart.hibernate.OrderDetailsPK" package="cart.hibernate.orderDetailsPK" resource="cart.hibernate.orderDetailsPK/OrderDetailsPK.hbm.xml"/>
When I try to run the testing main method, exception thrown from the program
887 [main] INFO org.hibernate.cfg.Configuration - Reading mappings from resource :
cart.hibernate.orderDetailsPK/OrderDetailsPK.hbm.xml
Initial SessionFactory creation failed.org.hibernate.MappingNotFoundException: resource: cart.hibernate.orderDetailsPK/OrderDetailsPK.hbm.xml not found
Exception in thread "main" java.lang.ExceptionInInitializerError
at cart.hibernate.HibernateUtil.buildSessionFactory(HibernateUtil.java:28)
at cart.hibernate.HibernateUtil.<clinit>(HibernateUtil.java:18)
at cart.hibernate.order.ManageOrder.main(ManageOrder.java:40)
Caused by: org.hibernate.MappingNotFoundException: resource: cart.hibernate.orderDetailsPK/OrderDetailsPK.hbm.xml not found
at org.hibernate.cfg.Configuration.addResource(Configuration.java:799)
at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:2344)
at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:2310)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:2290)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:2243)
at org.hibernate.cfg.Configuration.configure(Configuration.java:2158)
at cart.hibernate.HibernateUtil.buildSessionFactory(HibernateUtil.java:23)
... 2 more
After I read through the question ask by the others, I believe that the error in my code is caused by wrong mapping code. Hope you guys could help me to solve this problem. It would be nice if some simple examples of many-to-many mapping with extra column are provided.
I believe that your code is clean because the console told you MappingNotFoundException Once it loaded the hibernate file, it couldn't find it. Make sure that the hibernate file in the package of the model bean is not in the source.

Many-to-One w/ Composite key- Foreign key must have same number of columns as he referenced PK

Problem Summary
I am trying to map a many-to-one with a composite key. So far I haven't been able to locate another question that helps. I know how to map to a composite key with one-to-one, but it is not allowing me to map many-to-one.
Below you will see bhrvJournalDAO has a store_nbr column, that maps to transAcctgBuTxtDAO acctg_bu_id. How can I hit the composite key and tell it to only use the acctgBuId? I do not have a country code (which is the second part of the composite key).
From Here
<hibernate-mapping>
<class name="com.acctg.BhrvJournalDAO" table="transpo_acctg:bhrv_journal">
<id name="jeId" column="je_id">
<generator class="native"/>
</id>
<property name="bhrvInvoiceId" column="bhrv_invoice_id"/>
<property name="storeNbr" column="store_nbr"/>
<property name="loadId" column="load_id"/>
<many-to-one name="transAcctgBuTxt" class="TransAcctgBuTxtDAO" insert="false" update="false" cascade="all">
<column name="store_nbr"></column>
</many-to-one>
</class>
To Here
<hibernate-mapping>
<class name="TransAcctgBuTxtDAO" table="transpo_acctg:trans_acctg_bu_txt">
<composite-id name="transAcctgBuTxtPKDAO" class="TransAcctgBuTxtPKDAO">
<key-property name="acctgBuId" column="acctg_bu_id"/>
<key-property name="languageCode" column="language_code"/>
</composite-id>
<property name="acctgBuAbbr" type="java.lang.String">
<column name="acctg_bu_abbr" />
</property>
<property name="acctgBuDesc" type="java.lang.String">
<column name="acctg_bu_desc" />
</property>
<many-to-one name="transAcctgBuDAO" class="TransAcctgBuDAO" not-null="false"
insert="false" update="false" not-found="ignore" fetch="select">
<column name="acctg_bu_id" />
</many-to-one>
</class>
Mapping
<many-to-one name="transAcctgBuTxt" class="TransAcctgBuTxtDAO"
insert="false" update="false" cascade="all">
<column name="store_nbr"></column>
</many-to-one>
Composite Key Example
<one-to-one name="transAcctgBuTxt" class="TransAcctgBuTxtDAO" property-
ref="transAcctgBuTxtPKDAO.acctgBuId">
<column name = "store_nbr">
</one-to-one>
Error
Foreign key (FK47A121BB6617227C:transpo_acct:bhrv_journal [store_nbr]))
must have same number of columns as the referenced primary
key (transpo_acct:trans_acctg_bu_txt [acctg_bu_id,language_code])
Thanks in advance
Since TransAcctgBuTxtDAO has the composite id of 2 columns, you NEED to provide both values to uniquely identify one entity, period. Maybe you could reconsider if it is really a many-to-one relation between BhrvJournalDAO and TransAcctgBuTxtDAO. Mabye it is actually many-to-many.

need an Hibernate ORM mapping idea

I Have a table(student) with columns stu_id, stu_name, favourite_subject, subject_id
favourite_subject will have predefined values like maths,english etc.
if the value is maths, subject_id will have table: maths_subject's id.
meaning, based on favourite_subject value, subject_id will be pointing to the corresponding subject's id.
How can i implement in Hibernate ORM Framework.
<hibernate-mapping package="com.sample.project">
<class name="StudentDTO" table="student">
<meta attribute="class-description">class to hold student data</meta>
<id name="id" type="long" column="stu_id">
<generator class="increment"/>
</id>
<discriminator column="favourite_subject" type="string"/>
<property name="studentName" column="stu_name" not-null="true"/>
<!--?? here i don't know how to proceed. ??-->
<subclass name="??????" discriminator-value="Maths">
????
</subclass>
</class>
</hibernate-mapping>
all subjects will have their own tables & own corresponding entity classes.
assuming following class structure
class Student
{
private Subject favoriteSubject;
}
class MathSubject : Subject
{
}
class EnglishSubject : Subject
{
}
corresponding mapping
<hibernate-mapping package="com.sample.project">
<class name="Student" table="student">
<meta attribute="class-description">class to hold student data</meta>
<id name="id" type="long" column="stu_id">
<generator class="increment"/>
</id>
<property name="studentName" column="stu_name" not-null="true"/>
<any name="subject" id-type="Integer" meta-type="String" cascade="all">
<meta-value value="math" class="MathSubject"/>
<meta-value value="english" class="EnglishSubject"/>
<column name="favourite_subject"/>
<column name="subject_id"/>
</any>
</class>
</hibernate-mapping>

Delete element from Set

I have 2 classes Tema(Homework) and Disciplina (course), where a Course has a Set of homeworks.
In Hibernate i have mapped this to a one-to-many associations like this:
<class name="model.Disciplina" table="devgar_scoala.discipline" >
<id name="id" >
<generator class="increment"/>
</id>
<set name="listaTeme" table="devgar_scoala.teme">
<key column="Discipline_id" not-null="true" ></key>
<one-to-many class="model.Tema" ></one-to-many>
</set>
</class>
<class name="model.Tema" table="devgar_scoala.teme" >
<id name="id">
<generator class="increment" />
</id>
<property name="titlu" type="string" />
<property name="cerinta" type="binary">
<column name="cerinta" sql-type="blob" />
</property>
</class>
The problem is that it will add (insert rows in the table 'Teme') but it won't delete any rows and i get no exceptions thrown.
Im using the merge() method.
Although your question is unclear (how do you save and delete?), I'd suggest you need to set cascade:
<set cascade="all-delete-orphan">
As a sidenote - avoid names in your native language.
According to your description, I understand that a Tema cannot exist without its Disciplina: if you remove a Tema from the collection, you want it to be deleted. To tell Hibernate to do this, you must use cascade="all-delete-orphan".
<set name="listaTeme" table="devgar_scoala.teme" cascade="all-delete-orphan">
<key column="Discipline_id" not-null="true" ></key>
<one-to-many class="model.Tema" ></one-to-many>
</set>
Refer to the online documentation.

Categories