How to map a parent to a child with Hibernate? - java

I have the following classes
class Condition{
public Long id;
public Long ParentConditionId;
public Int order;
}
class NotCondition extends Condition {
public Condition childCondition;
}
class BooleanCondition extends Condition {
public Collection<Condition> children;
}
class StringCondition extends Condition {
public String value;
}
These classes are represented by a condition table with the following columns
Id bigint
Type varchar
ConditionOrder int
StringValue varchar
ParentConditionId bigint
How do I map the NotCondition to its child using hibernate mapping so that the childs ParentConditionId column contains the id of the NotCondition?
My mapping file is
<hibernate-mapping>
<class name="conditions.Condition" table="Condition">
<id column="Id" name="id" access="field">
<generator class="increment"/>
</id>
<discriminator type="string" column="Type"/>
<property name="order" column="ConditionOrder" access="field"/>
<property name="parentConditionId" column="ParentConditionId" access="field"/>
<subclass name="conditions.NotCondition" discriminator-value="NOT">
<!-- What to put here? -->
</subclass>
<subclass name="conditions.BooleanCondition" discriminator-value="BOOLEAN">
<list name="children" access="field" cascade="all" lazy="false">
<key><column name="ParentConditionId"></column></key>
<list-index column="ConditionOrder"/>
<one-to-many class="conditions.Condition"/>
</list>
</subclass>
<subclass name="conditions.StringCondition" discriminator-value="STRING" >
<property name="value" column="StringValue" access="field"/>
</subclass>
</class>
</hibernate-mapping>

explore these :
#Inheritance(strategy=InheritanceType.JOINED)
I suggest you to use annotations..
Below link contains both Annatation and xml configurations..
link here

First, in class Condition, I would replace:
public Long ParentConditionId;
with:
public Condition parentCondition;
I would map is like so:
<many-to-one name="parentCondition" class="conditions.Condition" column="ParentConditionId" />
then, I would map childCondition (in subclass NotCondition) as:
<one-to-one name="childCondition" class="conditions.Condition" property-ref="parentCondition" />

Related

How to map multiple many-to-one relations to the same table and same key using Hibernate?

I have two clases like these:
public class Message implements Serializable {
...
private int _messageId;
private String _message;
private String type;
...
And
public class MyClass implements Serializable {
private final int myClassId;
...
private final List<Message> messagesOfTypeA;
private final List<Message> messagesOfTypeB;
private final List<Message> messagesOfTypeC;
...
I want to persist both classes using hibernate.
Fields messagesOfTypeA, messagesOfTypeB and messagesOfTypeC group Message objects according to the type field from Message.
How can I map this one-to-many relation between MyClass and Message using XML hibernate mapping? (I'm using Hibernate 3.6)
MyClass
<hibernate-mapping>
<class name="MyClass" table="my_class">
<id name="myClassId" column="id">
<generator class="native"/>
</id>
<list name="messagesOfTypeA" cascade="all" fetch="join">
<key column="myclass_id"/>
<list-index column="idx"/>
<one-to-many class ="Message"/>
</list>
<list name="messagesOfTypeB" cascade="all" fetch="join">
<key column="myclass_id"/>
<list-index column="idx"/>
<one-to-many class ="Message"/>
</list>
<list name="messagesOfTypeC" cascade="all" fetch="join">
<key column="myclass_id"/>
<list-index column="idx"/>
<one-to-many class ="Message"/>
</list>
</class>
</hibernate-mapping>
Message
<hibernate-mapping>
<class name="Message" table="message">
<id name="_messageId" column="id">
<generator class="native"/>
</id>
<property name="_message" column="message"/>
<property name="type"/>
</class>
</hibernate-mapping>
You end up with a table message with the type discriminant and one FK
to the MY_CLASS table.
CREATE TABLE "MESSAGE"
( "ID" NUMBER(10,0) NOT NULL ENABLE,
"MESSAGE" VARCHAR2(255 CHAR),
"TYPE" VARCHAR2(255 CHAR),
"MYCLASS_ID" NUMBER(10,0),
"IDX" NUMBER(10,0),
PRIMARY KEY ("ID")
CONSTRAINT "FK_MY_CLASS" FOREIGN KEY ("MYCLASS_ID")
REFERENCES "MY_CLASS" ("ID") ENABLE
)

Hibrernate: Attribute "type" must be declared for element type "column"

I am trying to save to two tables in SQL server using Hibernate:
ORDER and ORDER_ITEM
I get an error:
Attribute "type" must be declared for element type "column".
Initial SessionFactory creation failed.org.hibernate.InvalidMappingException: Unable to read XML.
This produces a NullPointerException
If I understand correctly, this means that when I try to save to the order_item table, the getter for the foreign key is empty, but how would I set it if is designed to 'Autoincrement', I thought that hibernate would handle this in it's transaction.
Below are my POJO's and Hibernate mappings. I have omitted the getters and setters from this copy/paste, but they are present in my actual code
I am also successful in saving just to the ORDER table if I remove the set
Order.java:
public class Order {
public Order(){
super();
}
private int orderId;
private Set<LineItem> items;
private String strPhone;
private String strEmail;
private String strFirstName;
private String strLastName;
private String strParentFirstName;
private String strParentLastName;
private String strOrganizationName;
private String strOrganizationType;
private String strComment;
}
order.hbm.xml:
<hibernate-mapping>
<class name="dbobjects.Order" table="orders">
<id name="orderId" type="integer" column="order_id">
<generator class="increment"/>
</id>
<property name="strPhone" type="string" column="phone_number"/>
<property name="strFirstName" type="string" column="first_name"/>
<property name="strLastName" type="string" column="last_name"/>
<property name="strParentFirstName" type="string" column="parent_first_name"/>
<property name="strParentLastName" type="string" column="parent_last_name"/>
<property name="strOrganizationName" type="string" column="organization_name"/>
<property name="strOrganizationType" type="string" column="organization_type"/>
<property name="strComment" type="string" column="comments"/>
<set name="items" table="order_item" fetch="select" cascade="all">
<key>
<column name="orderId" type="java.lang.Integer"/>
</key>
<one-to-many class="dbobjects.LineItem"/>
</set>
</class>
LineItem.java:
public class LineItem {
public LineItem(){
super();
}
private int orderItemId;//this will be the primary key
private int orderId;//this is the foreign key to the order
private String age;
private String gender;
private String type;
private String itemSize;
private int itemQuantity;
}
lineItem.hbm.xml:
<id column="order_item_id" name="orderItemId" type="integer">
<generator class="increment"/>
</id>
<property column="age" name="age" type="string"/>
<property column="gender" name="gender" type="string"/>
<property column="quantity" name="itemQuantity" type="integer"/>
<property column="size" name="itemSize" type="string"/>
<property column="clothing_type" name="clothingType" type="string"/>
<many-to-one name="orderId" class="dbobjects.Order" fetch="select" column="order_id" type="java.lang.Integer"/>
This is where the error is thrown when I Instanciate the session:
**session = HibernateUtil.getSessionFactory().openSession();**←
try{
session.beginTransaction();
session.save(order);
session.getTransaction().commit();
So the question is: How do I handle this situation with 'autoincrement' primary key that is not accessible to another table as a foreign key
So, There were a few problems:
In order to submit a 'child' to the database, I needed to show who is the parent.
This means that my LineItem Class needed a
Order order;
property instead of a simple
private String orderID;
this was accomplished after the Order object was ready to be submitted to the DB but before the actual call:
for (LineItem item : order.getItems()) {
item.setOrder(order);
}
I also changed my DTD's from !DOCTYPE hibernate-configuration SYSTEM classpath://org/hibernate/hibernate-mapping-3.0.dtd"
to
!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"
Just add "type" attribute like this :
<column name="orderId" type="java.lang.Integer"/>
Try to replace :
<many-to-one name="orderId" column="order_id" class="dbobjects.Order" cascade="all">
<column name="orderId" type="java.lang.Integer"/>
</many-to-one>
by
<many-to-one name="orderId" column="order_id" class="dbobjects.Order" cascade="all"/>

Hibernate Single Table inheritance with self join

I have the following classes:
Guide class:
public abstract class Guide
{
private Long idGuide;
private String name;
private GuideContainer parent;
/** GETTERS & SETTERS*/
}
GuideContainer:
public class GuideContainer extends Guide
{
private Guide children;
/** GETTER & SETTERS */
}
GuideFile:
public class GuideFile extends Guide
{
private String uri;
/**GETTERS & SETTERS */
}
with the following mappings:
For Guide:
<hibernate-mapping>
<class name="Guide" table="guides" abstract="true">
<id name="idGuide" type="integer" column="idGuide">
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String" column="name" />
<discriminator column="type" type="java.lang.String" />
<many-to-one class="GuideContainer" fetch="join" name="parent">
<column name="parent" />
</many-to-one>
</class>
</hibernate-mapping>
GuideFile:
<hibernate-mapping>
<subclass extends="Guide" name="GuideFile" discriminator-value="file">
<property name="uri" type="java.lang.String" column="uri" />
</subclass>
</hibernate-mapping>
GuideContainer:
<hibernate-mapping>
<subclass extends="Guide" name="GuideContainer" discriminator-value="container">
<set fetch="select" inverse="true" lazy="true" name="children" sort="unsorted" table="children">
<key>
<column name="parent" not-null="false" />
</key>
<one-to-many class="Guide" />
</set>
</subclass>
</hibernate-mapping>
When I try to get all the guides with a given parent
Query query = getSession().createQuery("from Guide g where parent = :parent order by type").setParameter("parent", parent);
List<Guide> guides= query.list();
return guides;
I am getting the following exception:
IllegalArgumentException occurred calling getter of Guide.idGuide
And after that:
java.lang.IllegalArgumentException: object is not an instance of declaring class
What am I doing wrong?
Solved. Query should have been:
from Guide g where parent.idGuide = :parent order by type

org.hibernate.PropertyValueException: not-null property references a null or transient value:

I want to save an object to my sub-class ArticleZoning whose super class Zoning contain a List of Class zoneData which also contain a class ZoneCoordinate. When I save the object of my sub-class ArticleZoning it gives an exception.
org.hibernate.PropertyValueException: not-null property references a null or transient value: com.qait.cdl.eon.commons.domain.ZoneData._com.qait.cdl.eon.commons.domain.Zonning.zoneDatasBackref
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:101)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210).....
Here is *Zonning hbm*Mapping file:-
<class name="Zonning" table="zoning">
<id name="id" column="id" type="long">
<generator class="native" />
</id>
<list name="zoneDatas" lazy="false" cascade="all-delete-orphan" >
<key column="zoning_id" not-null="true"/>
<list-index column="idx" base="1" />
<one-to-many class="com.qait.cdl.eon.commons.domain.ZoneData" />
</list>
<many-to-one class="com.qait.cdl.eon.commons.domain.MagazineIssue" unique="true" column="issue_id" name="issue"/>
<property name="pageNumber" column="article_on_pageNumber" type="string" not-null="true" />
<joined-subclass name="ArticleZoning" extends="Zonning" table="article_zoning">
<key column="article_id"/>
<property name="articleTitle" column="article_title" type="string" not-null="true" />
<property name="articleOrder" column="article_order" type="int" not-null="true" />
<property name="articleFileId" column="article_file_id" type="string" not-null="true" />
<property name="articleType" column="article_type">
<type name="org.hibernate.type.EnumType">
<param name="type">12</param>
<param name="enumClass">com.qait.cdl.eon.common.constants.ArticleType</param>
</type>
</property>
<property name="articleSubTitle" column="article_sub_title" type="string" not-null="true" />
<property name="articleGenre" column="article_genre">
<type name="org.hibernate.type.EnumType">
<param name="type">12</param>
<param name="enumClass">com.qait.cdl.eon.common.constants.Genre</param>
</type>
</property>
</joined-subclass>
<joined-subclass name="AdvertisementZoning" extends="Zonning" table="advertisement_zoning">
<key column="advertisement_id" />
<property name="adVendor" column="ad_vendor" type="string" not-null="true" />
<property name="vendorUrl" column="vendor_url" type="string" not-null="true" />
<property name="adProduct" column="ad_product" type="string" not-null="true" />
<list name="adKeywords" table="ad_keywords" lazy="false" cascade="all">
<key column="ad_keywords_id" />
<list-index base="0" column="idx"/>
<element column="keywords" type="string" />
</list>
</joined-subclass>
</class>
Here is ZoneData Hbm
<id name="id" column="id" type="long">
<generator class="native" />
</id>
<property name = "zoneOrder" column = "zone_order" type = "int" not-null="true"/>
<property name = "zoneFileId" column = "zone_file_id" type = "string" not-null="true"/>
<property name = "zoneShape" column = "zone_shape" type = "string" not-null="true" access="field"></property>
<many-to-one name="coordinates" column="coordinates_id" lazy="false" class="com.qait.cdl.eon.commons.domain.ZoneCoordinates"
unique="true" not-null="true" cascade="all-delete-orphan"/>
</class>
Here is ZoneCoordinate hbm
<class name="ZoneCoordinates" table="zone_coordinates">
<id name="id" column="id" type="long">
<generator class="native" />
</id>
<property name = "leftTopX" column = "left_top_x" type = "float" not-null="true" />
<property name = "leftTopY" column = "left_top_y" type = "float" not-null="true" />
<property name = "rightBottomX" column = "right_bottom_x" type = "float" not-null="true" />
<property name = "rightBottomY" column = "right_bottom_y" type = "float" not-null="true" />
</class>
Here is Zoning pojo
class Zoning{
private List<ZoneData> zoneDatas =new ArrayList<>();
private MagazineIssue issue;
private String pageNumber;
//getter and setter
}
Here is ZoneData POJO
class ZoneData{
private int zoneOrder;
private String zoneFileId ;
private ZoneCoordinates coordinates;
private final String zoneShape = "RECT";
//getter and setter
}
Here is ArticleZoning POJO
class ArticleZoning extends Zoning{
private String articleTitle;
private String articleOrder;
private ArticleType articleType;
private String articleFileId;
private String articleSubTitle;
private Genre articleGenre;
//getter and setter
}
Here is ZoneCoordinate POJO
class ZoneCoordinate{
private float leftTopX;
private float leftTopY;
private float rightBottomX;
private float rightBottomY;
//getter and setter
}
First, ArticleZoning POJO has articleOrder as String type. Your Zonning.hbm says articleOrder is of int type.
Secondly, as zoning table is unable to save, hence its foreign key is null.

org.hibernate.exception.SQLGrammarException: could not get next sequence value

Am using Hibernate 3.6
Below is Employee class code.
public class Employee {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
Below is Employee.hbm.xml file,
<class name="com.testing.hibernate.Employee" table="HIB_EMPLOYEE">
<meta attribute="class-description">
This class contains the Employee details.
</meta>
<id name="id" type="int" column="id">
<generator class="sequence"></generator>
</id>
<property name="firstName" column="first_name" type="string"></property>
<property name="lastName" column="last_name" type="string"></property>
<property name="salary" column="salary" type="int"></property>
</class>
I have created sequence in Database. Below SS for reference. How can I overcome the exception that am getting?
You have to give the reference of the sequence to hibernate.
<generator class="sequence">
<param name="sequence">SEQUENCE_NAME</param>
</generator>
What annotation can i use to do this?
i've tried
#GeneratedValue(strategy=GenerationType.SEQUENCE , generator = <SEQUENCE_NAME>")
without any success
edit:
it seams that the generator have to also be created
#SequenceGenerator(name="<GEN_NAME>", sequenceName="<SEQUENCE_NAME>")

Categories

Resources