Hibernate one-to-one bidirectional mapping XML - java

I have 3 tables represented by the following diagram:
I am trying to build a REST API that when /template is accessed by GET method,
the returned JSON will contain a templateDefinition object, that also contains a template type object. To that end I have created the following mapping files:
Template.hbm.xml
<hibernate-mapping package="com.reporttemplateengine.models">
<class name="Template" table="TEMPLATE">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" column="NAME" type="string" />
<one-to-one name="templateDefinition" class="com.reporttemplateengine.models.TemplateDefinition" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
TemplateType.hbm.xml
<hibernate-mapping package="com.reporttemplateengine.models">
<class name="TemplateType" table="TEMPLATETYPE">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" column="NAME" type="string" />
</class>
</hibernate-mapping>
TemplateDefinition.hbm.xml
<hibernate-mapping package="com.reporttemplateengine.models">
<class name="TemplateDefinition" table="TEMPLATEDEFINITION">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="templateFile" column="TEMPLATE_FILE" type="blob" />
<property name="version" column="VERSION" type="int" />
<property name="active" column="ACTIVE" type="int" />
<many-to-one name="template" class="com.reporttemplateengine.models.Template"
column="template_id" unique="true" not-null="true" cascade="all" />
<many-to-one name="templateType" class="com.reporttemplateengine.models.TemplateType"
column="template_type_id" unique="true" not-null="true" cascade="all" />
</class>
</hibernate-mapping>
When I call the API, Hibernate logs this query:
select
this_.ID as ID1_0_1_,
this_.NAME as NAME2_0_1_,
templatede2_.ID as ID1_1_0_,
templatede2_.TEMPLATE_FILE as TEMPLATE_FILE2_1_0_,
templatede2_.VERSION as VERSION3_1_0_,
templatede2_.ACTIVE as ACTIVE4_1_0_,
templatede2_.TEMPLATE_ID as TEMPLATE_ID5_1_0_,
templatede2_.TEMPLATE_TYPE_ID as TEMPLATE_TYPE_ID6_1_0_
from
SYSTEM.TEMPLATE this_
left outer join
SYSTEM.TEMPLATEDEFINITION templatede2_
on this_.ID=templatede2_.ID
It should actually look like this:
select
this_.ID as ID1_0_1_,
this_.NAME as NAME2_0_1_,
templatede2_.ID as ID1_1_0_,
templatede2_.TEMPLATE_FILE as TEMPLATE_FILE2_1_0_,
templatede2_.VERSION as VERSION3_1_0_,
templatede2_.ACTIVE as ACTIVE4_1_0_,
templatede2_.TEMPLATE_ID as TEMPLATE_ID5_1_0_,
templatede2_.TEMPLATE_TYPE_ID as TEMPLATE_TYPE_ID6_1_0_
from
SYSTEM.TEMPLATE this_
inner join
SYSTEM.TEMPLATEDEFINITION templatede2_
on this_.ID=templatede2_.TEMPLATE_ID
This is also missing the template type object nested in templateDefinition. I do not know how to achieve this.

Related

Hibernate One-to-One foreign key using xml Not deleting orphan

I have two classes A and B.
<id name="id" type="java.lang.Integer" column="A_ID">
<generator class="identity" />
</id>
<property name="name" column="NAME"/>
<many-to-one name="B" cascade="all"
column="B_ID" unique="true"/>
</class>
<id name="id" type="java.lang.Integer" column="B">
<generator class="identity" />
</id>
<property name="n" column="N"/>
</class>
A.setB(new B());
When I save it works fine.
when I remove the record. A.setB(null);
I see a orphan record.
I see in A Table the column for B is null but on B Table there is still a record.
I tried to look in other solutions but couldnot find the ans to this.

How to select sub-level entity with Hibernate Criteria Query?

Let's say I have this named HQL (findRoomQuery):
select r from House h inner join h.roomList r
where h.address = :address and r.roomNo = :roomNo
The mapping of House entity is like this:
<class name="com.example.House" table="house">
<id name="id" column="id" type="long">
<generator class="assigned" />
</id>
<property name="address" column="address" type="string" length="100" not-null="false"/>
<set name="roomList" cascade="none" lazy="false" fetch="join" inverse="true">
<key>
<column name="house_id"/>
</key>
<one-to-many class="com.example.Room"/>
</set>
</class>
While the Room entity is like this:
<class name="com.example.Room" table="room">
<id name="id" column="id" type="long">
<generator class="assigned" />
</id>
<property name="houseId" column="house_id" type="long" not-null="true"/>
<property name="roomNo" column="room_no" type="string" length="4" not-null="false"/>
</class>
The relationship is a House can has one or many Room.
The code to execute the query is like this:
Query query = getSession().createQuery("findRoomQuery")
.setParameter("address", address)
.setParameter("roomNo", roomNo);
return query.list();
You can see the HQL return Room entities from select r (r is alias of h.roomList).
How to do the same thing with Hibernate Criteria Query?
Is it possible?
Try this one
Criteria criteria = session.createCriteria(House.class, "house");
criteria.createAlias("house.roomList", "roomList");
criteria.add(Restrictions.eq("house.address",address));
criteria.add(Restrictions.eq("roomList.roomNo", roomNo));
criteria.setProjection(Projections.property("roomList"));
Room r = (Room) criteria.uniqueResult();
replace
<property name="houseId" column="house_id" type="long" not-null="true"/>
to
<many-to-one name="houseId" class="com.example.House" fetch="select">
<column name="house_id" not-null="true" />
</many-to-one>

Add columns to table at runtime

I have a table mapped by the following xml file:
<hibernate-mapping auto-import="true" default-access="property"
default-cascade="none" default-lazy="true">
<class abstract="false" name="domain.CustomFlow"
table="CUSTOM_FLOW">
<id column="CUSTOM_FLOW_ID" name="id">
<generator class="native" />
</id>
<many-to-one name="customForm"
class="domain.CustomForm" fetch="select">
<column name="FORM_ID" not-null="true" />
</many-to-one>
<dynamic-component insert="true" name="customProperties"
optimistic-lock="true" unique="false" update="true">
</dynamic-component>
</class>
</hibernate-mapping>
I do update xml mapping at runtime so it will look like:
<dynamic-component insert="true" name="customProperties" optimistic-lock="true" unique="false" update="true"><property column="testColumn" generated="never" lazy="false" name="testColumn" not-null="false" optimistic-lock="true" type="java.lang.String" unique="false"/></dynamic-component>
How can I update the db schema at runtime. I'm using hibernate and spring?
have look here
it will show you how to update table structure on fly

Regarding one to one mapping in hibernate

I am a new bie to the world of hibernate could you please advise , I was going through one to one relationship in Hibernate,
As per my analysis , one to one hibernate relationships can be established by three ways..
1)Through Join concept
2)Same primary key in both the tables
3)Primary key and foriegn key relationship in both the tables
Please advise , the above three ways to achieve the one to one mapping is correct or I am missing something then please advise, and also please advise that the below hbm mapping files that I am using are correct one.if not then please advise.
1) Through Join concept :-
One way to achieve to one to one relationship is by joining concept , following xml is being used for that
<hibernate-mapping>
<class name="mypack.Person" table="person21">
<id name="personId" type="int">
<generator class="increment">
</generator>
</id>
<property name="name"/>
<join table="personAddress">
<key column="personId"/>
<many-to-one name="address" class="mypack.Address" column="addressId" unique="true" cascade="all"/>
</join>
</class>
<class name="mypack.Address" table="address21">
<id name="id" column="addressId" type="int">
<generator class="increment"/>
</id>
<property name="city"/>
<property name="state"/>
</class>
</hibernate-mapping>
2) Same primary key in both the tables :-
Using same primary key in both the tables , following hbm is being used for that
<class name="mypack.Address" table="address31">
<id name="id" column="addressId" type="int">
<generator class="increment"/>
</id>
<property name="city"/>
<property name="state"/>
</class>
<class name="mypack.Person" table="person31">
<id name="personId" type="int">
<generator class="foreign">
<param name="property">address</param>
</generator>
</id>
<property name="name"/>
<one-to-one name="address" class="mypack.Address"/>
</class>
</hibernate-mapping>
3)Primary key and foriegn key relationship in both the tables :-
Primary key in one table and foriegn key in another table. below is the hbm for this
<hibernate-mapping>
<class name="mypack.Person">
<id name="personId" type="int">
<generator class="increment"/>
</id>
<property name="name"/>
<many-to-one name="address" class="mypack.Address" column="addressId" unique="true" cascade="all"/>
</class>
<class name="mypack.Address">
<id name="id" column="addressId" type="int">
<generator class="increment"/>
</id>
<property name="city"/>
<property name="state"/>
</class>
</hibernate-mapping>
folks please advise.
I really think that join table is overkill here for a one-to-one mapping. For the other 2 solutions, please take a look at the following Hibernate documentation, everything is explained : http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html#mapping-declaration-onetoone.
For your second mapping (primary key association), both entities need to define a one-to-one mapping and one side of the relation also needs to specify the attribute constrained="true".
This is how I would write your second mapping :
<class name="mypack.Person" table="PERSONS">
<id name="id" type="int" column="PERSON_ID">
<generator class="increment"/>
</id>
<property name="name" type="string" column="NAME"/>
<one-to-one name="address" class="mypack.Address" cascade="all"/>
</class>
<class name="mypack.Address" table="ADDRESSES">
<id name="id" type="int" column="ADDRESS_ID">
<generator class="foreign">
<param name="property">address</param>
</generator>
</id>
<property name="city" type="string" column="CITY"/>
<property name="state" type="string" column="STATE"/>
<one-to-one name="person" class="mypack.Person" constrained="true"/>
</class>

Establish relationship from one table to another table in Hibernate

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.

Categories

Resources