So I got a new error and I narrowed it down to 2 classes. I think the mapping for the Map attribute of the "Grouping" class must be wrong. Here is the code:
Java Entities
public class Grouping {
private long id;
private Map<Meal, List<Integer>> mealsCounter;
}
public class Meal implements java.io.Serializable {
private long id;
private Grouping grouping;
}
Hibernate configuration
<hibernate-mapping>
<class name="data.Grouping" table="GROUPING">
<id name="id" type="long">
<column name="ID" />
<generator class="identity" />
</id>
<map name="mealsCounter" table="MEAL" lazy="true" access="field">
<key>
<column name="ID" />
</key>
<map-key type="data.Meal"></map-key>
<one-to-many class="data.Meal" />
</map>
</class>
<class name="data.Meal" table="MEAL">
<id name="id" type="long">
<column name="ID" />
<generator class="assigned" />
</id>
<many-to-one name="grouping" class="data.Grouping" fetch="join">
<column name="GROUPING" />
</many-to-one>
</class>
</hibernate-mapping>
When I try to persist and object I get the following errorlog:
Hibernate: insert into MEAL (NAME, GROUPING, ID) values (?, ?, ?)
756 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: -177, SQLState: 23503
756 [main] ERROR org.hibernate.util.JDBCExceptionReporter - integrity constraint violation: foreign key no parent; FK240BC3E3481002 table: MEAL
Related
I cannot get it to work. The error says Broken column mapping. It has to be one-sided one-to-one mapping. Only 1 part of composite-id is connected to the other entity. Channel gonna be inserted based on logged user's access channel. I do have 2 classes.
public class UserModel implements Serializable{
private final Long id;
private final UserLimitsModel userLimitsModel;
}
public class UserLimitsModel implements Serializable{
private final Long userId;
private final String channel;
}
Then 2 hibernate .xml mappings
<hibernate-mapping>
<class name="abcdefgh.UserLimitsModel" table="USER_LIMITS" lazy="false">
<composite-id>
<key-property name="userId" type="long">
<column name="USER_ID" not-null="true"/>
</key-property>
<key-property name="channel" type="string" length="20">
<column name="CHANNEL" not-null="true"/>
</key-property>
</composite-id>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="abcdefgh.UserModel" table="USER" lazy="false">
<id name="id" type="long">
<column name="ID" precision="19" scale="0" />
<generator class="sequence">
<param name="sequence_name">ID_SEQ</param>
</generator>
</id>
<one-to-one name="userLimitsModel" class="abcdefgh.UserLimitsModel" cascade="all"/>
</class>
</hibernate-mapping>
So the only connection is UserModel.id = UserLimitsModel.userId, while channel stays separate.
Hi the problem is that you are not joining with the primary key. Also the column name in UserModel is ID and in UserLimitsModel is USER_ID. You need to tell hibernate how to perform the join
you can do this by defining property-ref on the one-to-one element.
<one-to-one name="userLimitsModel" class="abcdefgh.UserLimitsModel" property-ref="userId" cascade="all"/>
property-ref (optional): the name of a property of the associated
class that is joined to the primary key of this class. If not
specified, the primary key of the associated class is used.
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.
I'm trying to achieve lazy load on the following.
User.java
public class User {
private int id;
private String userName;
private String password;
private Employee employee;
//getter and setters
}
User.hbm.xml
<hibernate-mapping>
<class name="com.site.dto.User" table="user">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="userName" type="string" update="false">
<column name="user_name" length="50" not-null="true" unique="true" />
</property>
<property name="password" type="string">
<column name="password" length="50" not-null="true" unique="true" />
</property>
<one-to-one name="employee" class="com.site.dto.Employee" fetch="select" cascade="save-update" />
</class>
</hibernate-mapping>
Employee.java
public class Employee implements Serializable{
private int id;
private String name;
private String email;
private User user;
// getter and setters
}
Employee.hbm.xml
<hibernate-mapping>
<class name="com.site.dto.Employee" table="employee">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="name" length="50" not-null="true" unique="true" />
</property>
<property name="email" type="string" update="false">
<column name="email" length="50" not-null="true" unique="true" />
</property>
// enforcing many-to-one to one-to-one by putting unique="true"
<many-to-one name="user" column="user_id" class="com.site.dto.User" unique="true" not-null="true" fetch="select" cascade="save-update" />
</class>
</hibernate-mapping>
First I'm getting the User Object based on username. Now I'm trying to load the employee object which gives me null pointer exception. So after digging on some debug, it seems to be using a select statement with wrong where clause. Here is the hibernate debug
select employee0_.id as id1_1_0_, employee0_.name as name2_1_0_, employee0_.email as email3_1_0_,employee0_.user_id as user_id25_1_0_, from employee employee0_ where employee0_.id=?
Why is the where clause is based on employee.id and not employee.user.id ? I think this is due to the reason on how one-to-one mapping works in hbm.xml configuration where one-to-one will be linked to child table's primary key id but not user_id. I'm forcing the many-to-one to one-to-one in employee by using unique="true". I can fetch the employee in Hibernate annotation's one-to-one by defining #Join-column but I can't figure out how to map the one-to-one in hbm.xml which should refer the child's user_id.
Figured out the solution a while back, but forget to post it.
The above problem is coz, by default one-to-one mapping will be implemented for a child table which have the parent's primary key as the Child's primary key. So if we're going to eliminate that default property and use one-to-one with many-to-one (unique=true), we should define property-ref
I've added property-ref in one-to-one mapping in User.hbm.xml and now it works fine.
<one-to-one name="employee" property-ref="user" class="com.site.dto.Employee" fetch="select" cascade="save-update" />
I just need to add an entry on a many to many table/object with hibernate (associate a song to a playlist) called SongsPlaylist.
the structure of the tables is so defined: Songs---->SongPlaylist<----Playlists
the mapping files (omitted not important portion of file):
<hibernate-mapping>
<class name="model.pojo.Songs" table="songs" catalog="dbname" lazy="false">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<set name="songsPlaylists" table="songs_playlist" inverse="true" lazy="true" fetch="select">
<key>
<column name="song" not-null="true" unique="true" />
</key>
<one-to-many class="model.pojo.SongsPlaylist" />
</set>
</class>
</hibernate-mapping>
<!-- Generated 24-set-2014 8.40.14 by Hibernate Tools 3.6.0 -->
<hibernate-mapping>
<class name="model.pojo.SongsPlaylist" table="songs_playlist" catalog="dbname" lazy="false">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<many-to-one name="songs" class="model.pojo.Songs" fetch="select">
<column name="song" not-null="true" unique="true" />
</many-to-one>
<many-to-one name="playlists" class="model.pojo.Playlists" fetch="select">
<column name="playlist" not-null="true" unique="true" />
</many-to-one>
</class>
</hibernate-mapping>
<!-- Generated 24-set-2014 8.40.14 by Hibernate Tools 3.6.0 -->
<hibernate-mapping>
<class name="model.pojo.Playlists" table="playlists" catalog="dbname" lazy="false">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<set name="songsPlaylists" table="songs_playlist" inverse="true" lazy="true" fetch="select">
<key>
<column name="playlist" not-null="true" unique="true" />
</key>
<one-to-many class="model.pojo.SongsPlaylist" />
</set>
</class>
</hibernate-mapping>
the pojo classes:
public class SongsPlaylist implements java.io.Serializable {
private Integer id;
private Songs songs;
private Playlists playlists;
(...)
}
public class Songs implements java.io.Serializable {
private Integer id;
private Set songsPlaylists = new HashSet(0);
(...)
}
public class Playlists implements java.io.Serializable {
private Integer id;
private Set songsPlaylists = new HashSet(0);
(...)
}
this is my function
s = new HibernateUtil().getSessionFactory().openSession();
transaction = s.beginTransaction();
(...)
q = s.createQuery("select sp from SongsPlaylist sp where sp.playlists = :p");
q.setParameter("p", p);
sp = q.list();
//already exists a song binded to that playlist
if(sp.size()>0){
Set<Playlists> sP = sp.get(0).getPlaylists().getSongsPlaylists();
sP.add(p);
song.setSongsPlaylists(sP);
s.save(s);
}else{
//or it is in another playlist...
q = s.createQuery("select sp from SongsPlaylist sp where sp.songs = :s");
q.setParameter("s", song);
sp = q.list();
if(sp.size()>0){
Set<Songs> sP = sp.get(0).getSongs().getSongsPlaylists();
sP.add(song);
p.setSongsPlaylists(sP);
s.save(p);
}else{
s.save(new SongsPlaylist(song, p));
}
}
}
transaction.commit();
s.close();
and it stucks on the transaction.commit(); (last lines) with
org.hibernate.HibernateException: Found shared references to a collection:
model.pojo.Songs.songsPlaylists
it looks like I do something wrong when persisting a Set<Playlists (the same when I try to do that with Set<Songs>) on a persistent object. what 's the best practice for this case in order to insert a "SongPlaylist" and to avoid the hibernate exception mentioned?
found a solution...
in the else block (instead of what I wrote), now is:
Set<Playlists> sP = song.getPlaylistses(); // terrific netbeans naming when automatic pojo mapping :-)
sP.add(p);
song.setPlaylistses(sP);
s.save(song);
and just a side bug, not related to this one, but
SongsPlaylist should not be as hbm file. hibernate mapping should be instead
<hibernate-mapping>
<class name="model.pojo.Songs" table="songs" catalog="dbname" lazy="false">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
(...)
<set name="playlistses" table="songs_playlist" inverse="false" lazy="false" fetch="select">
<key>
<column name="song" not-null="true" />
</key>
<many-to-many entity-name="model.pojo.Playlists">
<column name="playlist" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="model.pojo.Playlists" table="playlists" catalog="dbname" lazy="false">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<set name="songses" table="songs_playlist" inverse="false" lazy="false" fetch="select">
<key>
<column name="playlist" not-null="true" />
</key>
<many-to-many entity-name="model.pojo.Songs">
<column name="song" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
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>