I'm having a hard time to figure this thing out. I have managed to create this type of mapping using annotations, but XML configuration is giving me headache for hours. These are my POJOs (getters ans setters are omitted):
public class Stock implements Serializable {
private static final long serialVersionUID = 8724254922362918916L;
private int stockId;
private String stockCode;
private String stockName;
private Set<StockCategory> stockCategories;
}
public class Category implements Serializable {
private static final long serialVersionUID = -3719693878172387644L;
private int categoryId;
private String name;
private String desc;
private Set<StockCategory> stockCategories;
}
public final class StockCategoryId implements Serializable {
private static final long serialVersionUID = -6894097209574496516L;
private int stockId;
private int categoryId;
}
public class StockCategory implements Serializable {
private static final long serialVersionUID = 691323506089277225L;
private StockCategoryId stockCategoryId;
private Stock stock;
private Category category;
private Date createdDate;
private String createdBy;
}
And those are hibernate mapping files:
<class name="com.rmilovic.hibernate.examples.models.Stock" table="STOCK">
<id name="stockId" column="STOCK_ID" type="int">
<generator class="identity" />
</id>
<property name="stockCode" type="string">
<column name="STOCK_CODE" length="10" not-null="true" unique="true" />
</property>
<property name="stockName" type="string">
<column name="STOCK_NAME" length="10" not-null="true" unique="true" />
</property>
<set name="stockCategories" table="STOCK_CATEGORY" inverse="true"
lazy="true" fetch="select" cascade="all">
<key column="STOCK_ID" not-null="true" />
<one-to-many class="com.rmilovic.hibernate.examples.models.StockCategory" />
</set>
</class>
<class name="com.rmilovic.hibernate.examples.models.Category" table="CATEGORY">
<id name="categoryId" column="CATEGORY_ID" type="int">
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="NAME" not-null="true" length="10" unique="true" />
</property>
<property name="desc" type="string">
<column name="DESC" not-null="true" />
</property>
<set name="stockCategories" table="STOCK_CATEGORY" lazy="true" inverse="true"
fetch="select" cascade="all">
<key column="CATEGORY_ID" not-null="true" />
<one-to-many class="com.rmilovic.hibernate.examples.models.StockCategory" />
</set>
</class>
<class name="com.rmilovic.hibernate.examples.models.StockCategory" table="STOCK_CATEGORY">
<composite-id name="stockCategoryId"
class="com.rmilovic.hibernate.examples.models.StockCategoryId">
<key-property name="stockId" type="int" column="STOCK_ID" />
<key-property name="categoryId" type="int" column="CATEGORY_ID" />
</composite-id>
<property name="createdDate" type="date">
<column name="CREATED_DATE" not-null="true" length="10" unique="true" />
</property>
<property name="createdBy" type="string">
<column name="CREATED_BY" not-null="true" length="10" unique="true" />
</property>
<many-to-one name="stock" column="STOCK_ID"
class="com.rmilovic.hibernate.examples.models.Stock"
insert="false" update="false" />
<many-to-one name="category" column="CATEGORY_ID"
class="com.rmilovic.hibernate.examples.models.Category"
insert="false" update="false" />
</class>
Schema seems to be good but I'm getting:
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.rmilovic.hibernate.examples.models.Category
when I'm trying to save data.
This is the code which saves data:
final Session session = HibernateUtilities.openSession();
session.beginTransaction();
final Stock stock = new Stock("BLA", "Test");
final Category category = new Category("consumer", "consumer company");
final StockCategory stockCategory = new StockCategory(new Date(), "me");
stockCategory.setCategory(category);
stockCategory.setStock(stock);
stock.getStockCategories().add(stockCategory);
category.getStockCategories().add(stockCategory);
session.save(stock);
session.getTransaction().commit();
HibernateUtilities.closeSession();
Related
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"/>
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
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.
i have 2 classes, the Person class that have a ManyToOne relationship with Address class. When i trying to get the persons, the address object have null elements inside, why happens this? the lazy configuration dont works? I can save a Person Object with the Address in cascade.
Here is my code:
Person class:
public class Person implements java.io.Serializable {
private int idPerson;
private String name;
private String surname;
private String dni;
private Date dateBirth;
private String cellPhone;
private String landPhone;
private String email;
private String discr;
private Address address ;
public Person() {
}
// getters and setters
}
My Address class:
public class Address implements java.io.Serializable {
private int idAddress;
private City city;
private String street;
private String number;
private Integer apartament;
private int level;
public Address() {
}
//getters an setters
}
My two mapping files:
<hibernate-mapping>
<class name="com.efix.model.enterprise.Address" table="address" schema="public">
<id name="idAddress" type="int">
<column name="id_address" />
<generator class="assigned" />
</id>
<many-to-one name="city" class="com.efix.model.enterprise.City" cascade="all" lazy="false">
<column name="id_city" not-null="true" />
</many-to-one>
<property name="street" type="string">
<column name="street" length="60" not-null="true" />
</property>
<property name="number" type="string">
<column name="number" length="6" />
</property>
<property name="apartament" type="java.lang.Integer">
<column name="apartament" />
</property>
<property name="level" type="int">
<column name="level" not-null="true" />
</property>
</class>
</hibernate-mapping>
Above is the address maping and this is my peopel mapping:
<hibernate-mapping>
<class name="com.efix.model.enterprise.Person" table="person" schema="public">
<id name="idPerson" type="int">
<column name="id_person" />
<generator class="identity" />
</id>
<discriminator column="discr" type="string"/>
<property name="name" type="string">
<column name="name" length="40" not-null="true" />
</property>
<property name="surname" type="string">
<column name="surname" length="40" not-null="true" />
</property>
<property name="dni" type="string">
<column name="dni" length="40" />
</property>
<property name="dateBirth" type="date">
<column name="date_birth" length="13" />
</property>
<property name="cellPhone" type="string">
<column name="cell_phone" length="20"/>
</property>
<property name="landPhone" type="string">
<column name="land_phone" length="20"/>
</property>
<property name="email" type="string">
<column name="email" length="25" />
</property>
<many-to-one class="com.efix.model.enterprise.Address" name="address">
<column name="id_address" not-null="true"/>
</many-to-one>
<!-- Subclase Empleado -->
<subclass name="com.efix.model.enterprise.Employee" discriminator-value="Employee">
<property name="admissionDate" type="date">
<column name="admission_date" length="13" />
</property>
<property name="outDate" type="date">
<column name="out_date" length="13" />
</property>
<property name="position" type="string">
<column name="position" length="40" />
</property>
</subclass>
<!-- Sublcase cliente -->
<subclass name="com.efix.model.enterprise.Client" discriminator-value="Client">
<property name="notes" type="string">
<column name="notes" />
</property>
</subclass>
</class>
</hibernate-mapping>
My NullPointerException throws in this block of code:
ClientServiceImpl serviceImpl = new ClientServiceImpl();
for (Client cli : serviceImpl.findAll()) {
System.out.println(cli.getAddress().getNumber());
Thanks for yours reply!! My error was in a expression inside a . I was references to a non existed property!!
I've got table in MySQL database with this structure:
And hibernate mapping for object PatientDAO here:
<?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>
<class name="cz.cvut.fit.genepi.models.PatientDAO" table="patient">
<id name="_id" type="int">
<column name="id" precision="6" scale="0" not-null="true" />
<generator class="assigned" />
</id>
<property name="_nin" type="long">
<column name="nin" length="20" not-null="false" />
</property>
<property name="_birthday" type="date">
<column name="birthday" length="7" not-null="true" />
</property>
<property name="_gender" type="string">
<column name="gender" length="10" not-null="true" />
</property>
<property name="_doctor_id" type="int">
<column name="doctor_id" precision="6" scale="0" not-null="false" />
</property>
<property name="_deleted" type="int">
<column name="deleted" precision="1" scale="0" not-null="false" />
</property>
<property name="_checked" type="int">
<column name="checked" precision="1" scale="0" not-null="false" />
</property>
<property name="_contact_id" type="int">
<column name="contact_id" precision="6" scale="0" not-null="false" />
</property>
<property name="_comment_id" type="int">
<column name="comment_id" precision="6" scale="0" not-null="false" />
</property>
</class>
</hibernate-mapping>
But when I'm trying to get some sample data from dtb and print them out, I get only 0. This happens for any possible property of Patient DAO. And for any id of searched patient.
I'm sure, that patient with id==0 is contained in that table.
findByID function:
public T findByID(Class<T> myClass, int id) {
Session hibernateSession = this.getSession();
T t = null;
t = (T) hibernateSession.get(myClass, id);
return t;
}
part of PatientDAO (without setters and getters):
public class PatientDAO implements java.io.Serializable {
/**
* generated serialVersionUID
*/
private static final long serialVersionUID = -8172690860460945951L;
private int _id;
private long _nin;
private Date _birthday;
private String _gender;
private int _doctor_id;
private int _deleted;
private int _checked;
public int get_checked() {
return _checked;
}
}
My personal tip is that I got there something wrong in my mapping, because for simplier objects it worked well. But I'm quite new to hibernate, so I can't figure out, what can be there wrong.. I'd be really glad if someone could help.
problem was in bad mapping... I actually dind't see, that nin should be varchar and I declared it as long