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.
Related
I have many Model Entities like
class Employee {
private Integer id;
private String name;
}
class Address {
private Integer id;
private String address;
}
and many more..
Can we map all Entities together in single hbm xml mapping file?
I know it might not be good practice. but Still can we do it? If yes then how ?
Yes. It is possible to use a single mapping file.
Something like this:
<hibernate-mapping>
<class name="Employee" table="employee">
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="native"/>
</id>
<property name="name" type="java.lang.String">
<column name="name"/>
</property>
</class>
<class name="Address" table="address">
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="native"/>
</id>
<property name="address" type="java.lang.String">
<column name="address"></column>
</property>
</class>
</hibernate-mapping>
Yes you can do this, the dtd (http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd) allows multiple class elements in hibernate-mapping:
<!ELEMENT hibernate-mapping (
...
(class|subclass|joined-subclass|union-subclass)*,
...
)>
Even the documentation (http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch05.html#mapping-declaration, second code block) maps as an example a Cat and a Dog class in the same file.
I have 2 classes:
public class Car {
private Integer id;
private List<CarOrder> carOrders;
}
public class CarOrder {
private Car car;
private Long endDate;
private Long id;
}
and hibernate mapping
<class entity-name="car" name="test.es.Car" table="CARS" schema="ARK_ES">
<cache usage="read-write"/>
<id name="id" column="ID">
<generator class="sequence">
<param name="sequence">ES_SEQUENCE</param>
</generator>
</id>
<bag name="carOrders" inverse="true" lazy="true">
<cache usage="read-write"/>
<key column="CAR_ID"/>
<one-to-many not-found="ignore" entity-name="carOrder"/>
</bag>
</class>
<class entity-name="carOrder" name="temp.es.CarOrder" table="CAR_ORDERS" schema="ARK_ES">
<cache usage="read-write"/>
<id name="id" column="ID">
<generator class="sequence">
<param name="sequence">ES_ORDER_SEQUENCE</param>
</generator>
</id>
<property name="endDate" column="END_DATE"/>
<many-to-one name="car" entity-name="car">
<column name="CAR_ID"/>
</many-to-one>
</class>
I need to load all cars and car orders with endDate greater than some value. Also i need to cache the query for car order. i tried to use hibernate filters, but they are not cached. Is it possible to achieve this using hibernate api without custom queries?
I forgot to mention that car can have no orders, but it must be in result.
Thanks.
So you can use the #fitler and #filterdef annotation on your collection class. But then it is very important to enable the filters in the session. Please follow this link on how to enable filters, they are not enabled by default.
How to enable hibernate filter for sessionFactory.getCurrentSession()?
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.
I'm sure there must be thousands of examples demonstrating this association but I can't seem to find one anywhere.
I have a one-many relationship from Parent-Child and a many-one relationship from Child-Parent:
class Parent {
private Long id;
private String name;
private List<Child> children;
}
class Child {
private Long id;
private String name;
private Parent parent;
}
I'm expecting to end up with 2 tables that look as follows:
Parent
- id : bigint
- name : varchar
Child
- id : bigint
- parent_id : bigint
- sequence : bigint
- name : varchar
Have I got the right idea? If so does anyone know what I need to put in my mapping file so that when a parent is deleted so too are it's children.
Thanks in advance.
James
Found the solution in the end although I don't understand why I need insert="false" and update="false":
<hibernate-mapping>
<class name="foo.Parent" table="Parent">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" type="java.lang.String" column="name" length="50" />
<list name="children" cascade="all">
<key column="parent_id" />
<index column="sequence" />
<one-to-many class="foo.Child" />
</list>
</class>
<class name="foo.Child" table="Child">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" type="java.lang.String" column="name" length="50" />
<many-to-one name="parent" class="foo.Parent" column="parent_id" insert="false" update="false" />
</class>
</hibernate-mapping>
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>