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>
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 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 domain Classes - User, Role, Group, Group Role
User Domain
private long id,
private String userName,
private String password,
Set<Role> roles = new HashSet<Role>();
User.hbm.xml
<hibernate-mapping package="uk.co.jmr.sdp.domain">
<class name="User" table="user">
<id name="id" unsaved-value="-1">
<generator class="native"/>
</id>
<property name="userName" column="user_name"/>
<property name="password" column="password"/>
<property name="emailId" column="email_id"/>
<set name="roles" table="user_role" lazy="false" cascade="all">
<key column="user_id"/>
<many-to-many column="role_id" class="Role" fetch="join"/>
</set>
<set name="groupRoles" table="user_grouprole" lazy="false" cascade="all">
<key column="user_id"/>
<many-to-many column="group_role_id" class="GroupRole" fetch="join"/>
</set>
</class>
</hibernate-mapping>
I have user_grouprole table as a join table for an User and Set of grouproles
I have user_role table as a join table for an user and set of roles
Group Domain
private long id;
private String groupName;
private Set<Role> roles = new HashSet<Role>();
Group.hbm.xml
<hibernate-mapping package="uk.co.jmr.sdp.domain">
<class name="Group" table="group">
<id name="id" unsaved-value="-1">
<generator class="native"/>
</id>
<property name="groupName" column="group_name"></property>
<set name="roles" table="group_role" lazy="false" cascade="all">
<key column="group_id"/>
<many-to-many column="role_id" class="Role" fetch="join"/>
</set>
GroupRole
private long id;
private Role role;
private Group group;
GroupRole.hbm.xml
<class name="GroupRole" table="group_role">
<id name="id" unsaved-value="-1">
<generator class="native"/>
</id>
<many-to-one name="role" class="uk.co.jmr.sdp.domain.Role"
column="role_id" lazy="false" not-null="true" />
<many-to-one name="group" class="uk.co.jmr.sdp.domain.Group"
column="group_id" lazy="false" not-null="true" />
</class>
</hibernate-mapping>
When I try to test with a main class, I get a mapping error like a hibernate mapping error like
Foreign key (FK5110401A8398947:user_grouprole [group_role_id])) must have same number of columns as the referenced primary key (group_role [group_id,role_id])
What is this error? Why I get this error? What should I do to rectify this error??? Any Solutions ? Can anyone explain what is this error?
Thanks in Advance
Your error is telling that your table USER contains a foreign key on a column named GROUP_ROLE_ID, but your referenced table, GROUP_ROLE, defines it's primary key with two columns ROLE_ID and GROUP_ID, which by the way is very common for relationship tables.
Seems to me that the only reason that you are mapping GroupRole is because you need it in your User entity. Well, if your domain model is really correct, then you need to think about how you want to synchronize your User's FK and GroupRole's PK. For that you might:
Create a PK object for your composite key or define your ID's correctly in your mappings;
Change your PK definition in GroupRole table.
Best regards.
I have a table Project with fields
ID
PROJECT_BASELINE_ATTRIBUTES_ID (FK for table PROJECT_BASELINE_ATTR)
This table has the following mapping
<hibernate-mapping package="com.initech.db.model">
<class name="com.initech.db.model.Project" table="PROJECT">
<id name="id" column="id" type="java.lang.Long">
<meta attribute="use-in-tostring">true</meta>
<generator class="sequence">
<param name="sequence">PROJECT_ID_SEQ</param>
</generator>
</id>
<many-to-one name="projectBaselineAttributes" column="PROJECT_BASELINE_ATTRIBUTES_ID" class="com.initech.db.model.ProjectBaselineAttributes" cascade="all" not-null="true">
<meta attribute="use-in-tostring">true</meta>
</many-to-one>^
</class>
</hibernate-mapping>
The respective Project.java class has the fields
private Long id;
private ProjectBaselineAttributes projectBaselineAttributes;
Furthermore, I have a table PROJECT_BASELINE_ATTR, containing the field
ID
The Hibernate mapping:
<hibernate-mapping package="com.initech.db.model">
<class name="com.initech.db.model.ProjectBaselineAttributes" table="PROJECT_BASELINE_ATTR">
<id name="id" column="id" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">PRO_BASE_ATTR_ID_SEQ</param>
</generator>
</id>
<set name="projects" table="PROJECT" inverse="true" lazy="true" fetch="select">
<key>
<column name="PROJECT_BASELINE_ATTRIBUTES_ID" precision="22" scale="0" not-null="true" />
</key>
<one-to-many class="com.initech.db.model.Project" />
</set>
</class>
</hibernate-mapping>
The respective ProjectBaselineAttributes.java class has the fields
private Long id;
private Set projects = new HashSet();
The current mapping is not ideal, as the relationship between the two tables is actually one-to-one, but in the ProjectBaselineAttributes I have a set of Projects, even though there is always one Projet for one ProjectBaseLineattributes. What should the mapping look like for ProjectBaselineAttributes so that I can get the associated Project "singularly", i.e. so that the class ProjectBaselineAttributes.java would look like this:
private Long id;
private Project project;
Here's the section of the Hibernate documentation which details how to map such a bidirectional one-to-one association using a foreign key.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
unique="true"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<one-to-one name="person"
property-ref="address"/>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
You can try the below mappings as told in this example.
In the parent bean,
<one-to-one name="one2oneSubA1" class="com.manu.hibernate.mappings.domain.ASub1" cascade="all"
property-ref="parent"/>
In the child bean,
<many-to-one name="parent"
class="com.manu.hibernate.mappings.domain.AMain" column="a_id"
unique="true" cascade="save-update" />
I have 2 tables, one table is
City Table ( int id, string name)
and my another table is
Distance table(int id,int cityId (FK city),int neighbourId(FK city))
I want to use Hibernate but I can't establish a relationship between these tables in Hibernate.
what about something like
<class name="City" table="CITIES">
<id name="id" type="integer">
<generator class="native" />
</id>
<property name="name" />
<set name="neighbours" table="DISTANCES">
<key column="city_id" />
<many-to-one name="neighbour" class="City" />
</set>
</class>
didn't test it though.
Ok, I can see any problem to do it normally.
<class name="City" table="CITY">
<id name="id" type="integer">
<generator class="native" />
</id>
<property name="name" />
</class>
<class name="Distance" table="DISTANCE">
<id name="id" type="integer">
<generator class="native" />
</id>
<many-to-one name="city" column="cityId" class="City"/>
<many-to-one name="neighbour" column="neighbourId" class="City"/>
</class>
didn't test it neither.