I have a class Event containing a composite primary key (start date and end date).
A EventPlanning class holds a Set of such Event objects and has to persist them using hibernate with XML.
I can do this for classes with a common primary key:
<!-- EventPlanning xml -->
....
<id name="id" column="id">
<generator class="native" />
</id>
<property name="name" column="name" type="string" update="false" />
<set name="events" table="events" cascade="all">
<key column="event_id"> // ###### here! ######
</key>
<one-to-many class="myPackage.Event" />
</set>
...
but I can't find out how this works with a composite key..
replacing the <key column="event_id"> with the following code doesn't work:
<key>
<property column="start_date" />
<property column="end_date" />
</key>
I'd be glad if somebody can show me the right syntax! :)
the Event xml looks like this:
<class name="myPackage.Even" table="events">
<composite-id>
<key-property name="startDate" column="start_date" type="date" />
<key-property name="endDate" column="end_date" type="date" />
</composite-id>
<property name="signinDeadline" column="signin_deadline"
type="date" />
<property name="confirmationDeadline" column="confirmation_deadline"
type="date" />
<set name="participants" table="participants" cascade="all">
<key column="event_id">
</key>
<one-to-many class="myPackage.Participants" />
</set>
</class>
thanks in advance! :)
Something like this works for me:
<class name="YourClass" table="your_table" ...>
<composite-id name="compositeId" class="DoubleDate">
<key-property name="start_date" column="start_date"/>
<key-property name="end_date" column="end_date"/>
</composite-id>
...
</class>
public class DoubleDate implements Serializable {
private Date start_date, end_date;
public DoubleDate() {
}
// setters, getters
}
public class YourClass {
private DoubleDate compositeId;
// public no args ctr, getters, setters, etc
}
After having now worked longer with JPA and Hibernate, I'd just say that you simply should not use composite primary keys. Caches use ids as keys that point to cached values, data retrieving methods like get and load expect the id as parameter etc.
The advantages gained by having an id field pay off against the additional space it needs.
Related
I have two objets like:
public class Object1 implements Serializable {
protected Integer id; // This is the PK in the xml mapping
protected Integer otherId;
}
public class Object2 implements Serializable {
protected Integer id; // This is the PK in the xml mapping
protected Set<Object1> object1List; // I want to relate this set against the "otherId" attribute
}
And I have this hibernate XML mappings:
<class name="Object1" table="Object1Table">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="otherId" type="java.lang.Integer">
<column name="other_id"></column>
</property>
</class>
<class name="Object2" table="Object2Table">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<set name="object1List" table="Object1Table" lazy="false" fetch="join" >
<key column="other_id" /> // This is not working
<one-to-many class="Object1" />
</set>
</class>
But I don't know how to relate the "set" mapping against the "other_id" attribute, it only works against the PK "id" of the "Object1" table.
Does anyone know how to solve this situation?
I think you need to mark the <set as inverse. Like crizzis mentioned, you'd be better off if you use the annotation model. A lot more people can help you with the annotation model. Apart from that, the HBM XML mapping will be replaced with the JPA orm.xml mapping at some point, so I wouldn't use that approach anymore.
i have a class attendance like
public class Attendance implements Serializable
{
private Integer id,userId;
private Date date;
private OfficeTime officeTime;
private Set<TimeSlice> timeSlices;
public Attendance()
{
}
}
now i'm try to make two primary key's using hibernate mapping composite-id
<hibernate-mapping>
<class name="Attendance">
<composite-id>
<key-property name="id"><generator class="increment"/></key-property>
<key-property name="date" />
</composite-id>
<property name="userId" />
<set name="timeSlices" cascade="all" >
<key column="attendanceId" />
<one-to-many class="TimeSlice" />
</set>
<many-to-one name="officeTime" class="OfficeTime"
column="office_id" unique="true" not-null="true"
cascade="all" />
</class>
</hibernate-mapping>
while am doing like this i got error The content of element type "key-property" must match "(meta*,column*,type?)".
how to set two primary key's and one must be increment automatically.Thanks in advance.
Your current configuration is not following the schema that is set for the composite-id element.
Here is the schema doc for the composite id:
<composite-id name="propertyName" class="ClassName" mapped="true|false" access="field|property|ClassName"> node="element-name|." <key-property name="propertyName" type="typename" column="column_name"/> <key-many-to-one name="propertyName class="ClassName" column="column_name"/> ...... </composite-id>
This is a sample configuration:
<composite-id>
<key-many-to-one name="username" class="org.myclass.UserDB" column="user_name"/>
<key-property name="role" type="string" column="role_name"/>
</composite-id>
The documentation for this is here: https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html#mapping-declaration-compositeid
I'm stuck at the hibernate xml mapping configuration.
I've established some tables with foreign key constraints in my MSSQL database:
Table ItemsBase
ID int primary-key
ItemID int unique index
... some more columns
Table Others
ID int primary-key
ItemID int unique index
... some more columns
The foreign key constraint is configured to connect these two tables by using the column "ItemID".
My ItemsBase.hbm.xml files looks like:
<hibernate-mapping>
<class name="de.delife.sql.ItemsBase" table="ItemsBase" schema="dbo" catalog="Delife_Plenty">
<id name="id" type="int">
<column name="ID" />
<generator class="assigned" />
</id>
<property name="itemId" type="java.lang.Integer">
<column name="ItemID" unique="true" />
</property>
<set name="otherses" table="Others" inverse="true" lazy="true" fetch="select">
<key property-ref="itemId">
<column name="ItemID" />
</key>
<one-to-many class="de.delife.sql.Others" not-found="ignore" />
</set>
</class>
</hibernate-mapping>
and the Others.hbm.xml files looks like:
<hibernate-mapping>
<class name="de.delife.sql.Others" table="Others" schema="dbo" catalog="Delife_Plenty">
<id name="id" type="int">
<column name="ID" />
<generator class="assigned" />
</id>
<many-to-one name="itemsBase" class="de.delife.sql.ItemsBase" fetch="select" property-ref="itemId">
<column name="ItemID" unique="true" />
</many-to-one>
</class>
</hibernate-mapping>
Everything looks fine for me, but when I run my program I get a hibernate error:
property [itemId] not found on entity [de.delife.sql.Others]
I have an established relation between ItemsBase and a table named ItemsProperties and it works, but with this "pretty" table "Others" I'm stuck.
I would be glad, if someone can help me on this matter. Thx in advance.
Try like this. I tried and its working for me.
<set name="otherses" table="Others" inverse="true" lazy="true" fetch="select">
<key column="itemId" foreign-key="itemId" property-ref="itemId"/>
<one-to-many class="de.delife.sql.Others" not-found="ignore" />
</set>
Item id should be defined as a property in Others.hbm.xml:
<property name="itemId" column="ItemId"/>
While trying to achieve one to many mapping for class Person and Address I get the following exception :org.hibernate.MappingException: could not instantiate id generator.
I don't know the reason for this. What could be the reason I am getting this exception ?
<class name="pojo.Person" table="person">
<id name="personID" column="p_id">
<generator class="increment" />
</id>
<property name="personName" column="p_name" />
<set name="addressSet" table="address" cascade="all">
<key column="p_id" />
<one-to-many class="pojo.Address" />
</set>
</class>
<class name="pojo.Address" table="address">
<id name="a_id" column="a_id">
<generator class="foreign" />
</id>
<property name="personAddress" column="p_address" />
</class>
Sql that created table:
CREATE TABLE person(p_id INTEGER,p_name TEXT,PRIMARY KEY(p_id));
CREATE TABLE address(a_id INTEGER,p_address TEXT);
Note: One person can have more than one address
You need to change generator class from foreigner to increment in a key of your Address entity. For details, see this answer where I already mentioned that.
Need some help on understanding how to do this; I'm going to be running recursive 'find' on a file system and I want to keep the information in a single DB table - with a self-referencing hierarchial structure:
This is my DB Table structure I want to populate.
DirObject Table:
id int NOT NULL,
name varchar(255) NOT NULL,
parentid int NOT NULL);
Here is the proposed Java Class I want to map (Fields only shown):
public DirObject {
int id;
String name;
DirObject parent;
...
For the 'root' directory was going to use parentid=0; real ids will start at 1, and ideally I want hibernate to autogenerate the ids.
Can somebody provide a suggested mapping file for this please; as a secondary question I thought about doing the Java Class like this instead:
public DirObject {
int id;
String name;
List<DirObject> subdirs;
Could I use the same data model for either of these two methods ? (With a different mapping file of course).
--- UPDATE: so I tried the mapping file suggested below (thanks!), repeated here for reference:
<hibernate-mapping>
<class name="my.proj.DirObject" table="category">
...
<set name="subDirs" lazy="true" inverse="true">
<key column="parentId"/>
<one-to-many class="my.proj.DirObject"/>
</set>
<many-to-one name="parent"
class="my.proj.DirObject"
column="parentId" cascade="all" />
</class>
...and altered my Java class to have BOTH 'parentid' and 'getSubDirs' [returning a 'HashSet'].
This appears to work - thanks, but this is the test code I used to drive this - I think I'm not doing something right here, because I thought Hibernate would take care of saving the subordinate objects in the Set without me having to do this explicitly ?
DirObject dirobject=new DirObject();
dirobject.setName("/files");
dirobject.setParent(dirobject);
DirObject d1, d2;
d1=new DirObject(); d1.setName("subdir1"); d1.setParent(dirobject);
d2=new DirObject(); d2.setName("subdir2"); d2.setParent(dirobject);
HashSet<DirObject> subdirs=new HashSet<DirObject>();
subdirs.add(d1);
subdirs.add(d2);
dirobject.setSubdirs(subdirs);
session.save(dirobject);
session.save(d1);
session.save(d2);
you can get the children from parent
<set name="subdirs" lazy="false" cascade="all-delete-orphan" inverse="true">
<key column="parentid " />
<one-to-many class="DirObject" />
</set>
parent from child
<many-to-one name="parent" class="DirObject">
<column name="parentid" />
</many-to-one>
I believe this will work ... completely untested.
<hibernate-mapping>
<class name="my.proj.DirObject" table="category">
...
<set name="subDirs" lazy="true" inverse="true">
<key column="parentId"/>
<one-to-many class="my.proj.DirObject"/>
</set>
<many-to-one name="parent"
class="my.proj.DirObject"
column="parentId" cascade="all" />
</class>
</hibernate-mapping>
You can actually have the following Java entity:
public DirObject {
int id;
String name;
DirObject parent;
List<DirObject> subdirs;
...
}
And map it on the DIROBJECT table:
ID int NOT NULL,
NAME varchar(255) NOT NULL,
PARENTID int NOT NULL);
Using the following mapping:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="mypackage">
<class name="DirObject" table="DIROBJECT">
<id name="id" type="int">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="string">
<column name="NAME" length="150" not-null="true" unique="false" index="NAME" />
</property>
<bag name="subdirs" lazy="false" cascade="all-delete-orphan" inverse="true">
<key column="PARENTID" />
<one-to-many class="DirObject" />
</bag>
<many-to-one name="parent" class="DirObject">
<column name="PARENTID" />
</many-to-one>
</class>
</hibernate-mapping>