Hibernate - insert data with one to many relationship - java

I am trying to insert data into a Patient table, which has a many-to-one relationship with Site. Site has a one-to-many relationship with Patient.
However, I get a org.postgresql.util.PSQLException: ERROR: insert or update on table "patients" violates foreign key constraint "fk_427e3ubwhw8n7a4id3mmrmjgj"
Detail: Key (patient_id)=(31) is not present in table "sites".
I have tried to create a set of patients, add my patient to this set, create a site object, then use this object to set the patients. I am not sure which part of this is going wrong.
Session session = this.getFactory().openSession();
Transaction transaction = null;
try{
transaction = session.beginTransaction();
Date parsedDob = Date.valueOf(dob);
Date parsedDateReg = Date.valueOf(dateReg);
Site site = new Site();
site.setSiteId(1);
IPatient p = new Patient();
p.setFirstName(firstName);
p.setLastName(lastName);
p.setDob(parsedDob);
p.setDateRegistered(parsedDateReg);
p.setSite(site);
Set<IPatient> patientSet = new HashSet<IPatient>();
patientSet.add(p);
site.setPatients(patientSet);
session.save(site);
session.save(p);
transaction.commit();
}catch(Exception e){
e.printStackTrace();
}
My Patient.hbm.xml file is:
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.example.model">
<class name="Patient" table="patients">
<id name="patientId" column="patient_id">
<generator class="sequence" />
</id>
<version name="version" column="version" />
<property name="firstName" column="first_name" />
<property name="lastName" column="last_name" />
<property name="dob" column="dob" />
<property name="gender" column="gender" />
<property name="dateRegistered" column="date_registered" />
<many-to-one name="site" class="com.example.model.Site" not-null="true" />
<set name="visits" cascade="all">
<key column="visit_id" />
<one-to-many class="Visit" />
</set>
</class>
My Site.hmx.xml is:
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.example.model">
<class name="Site" table="sites">
<id name="siteId" column="site_id">
<generator class="sequence" />
</id>
<version name="version" column="version" />
<property name="name" column="name" />
<set name="patients" cascade="all">
<key column="patient_id" />
<one-to-many class="Patient" />
</set>
</class>
My Patient.java
public class Patient implements IPatient{
private Integer version;
private Integer patientId;
private Set<IVisit> visits;
private Site site;
private String firstName;
private String lastName;
private Date dob;
private Gender gender;
private Date dateRegistered;
public Patient(){
}
}
My Site.java
public class Site {
private Integer siteId;
private Integer version;
private Set<IPatient> patients;
private String name;
public Site(){
}
}

After the line below you should save your site object to db;
site.setSiteId(1);
session.save(site);
After that you can set site object to patient;
p.setSite(site);

Related

Problem with hibernate mapping (change anotations with xml)

I have a spring-hibernate application which work fine with JPA anotations, but I want to change anotations with xml configuration, but but I get this error:
org.hibernate.hql.internal.ast.QuerySyntaxException: User is not mapped [FROM User]
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: User is not mapped [FROM User]
User.java
package com.fp.models;
public class User implements UserDetails {
private long id;
private String username;
private String password;
private Set<Role> authorities;
public User() {
}
User.hbm.xml
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.fp.models.User" table="users">
<id name="id" type="long" column="user_id">
<generator class="native"/>
</id>
<property name="username" column="username" type="string"/>
<property name="password" column="password" type="string"/>
<set name="authorities" table="users_roles"
inverse="false" lazy="true" fetch="select" cascade="all" >
<key>
<column name="user_id" not-null="true" />
</key>
<many-to-many entity-name="com.fp.models.Role">
<column name="role_id" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
HibernateConfiguration.java -> https://pastebin.com/DrcGSBAp
this is the configuration which i use with the anotations
Method for test:
#Override
public int listAllUsers() {
try (Session session = sessionFactory.openSession()) {
String hql = "FROM User";
Query query = session.createQuery(hql);
if (query.list().size() == 0) {
return 0;
} else {
return 1;
}
} catch (HibernateException he) {
System.out.println(he.getMessage());
throw he;
}
}

Hibernate - Mapping association on un-related objects in xml

I have 2 classes:
User
RentedCar
public class User implements Serializable{
private String userName;
private Integer userId;
private String userParent;
}
public class RentedCar implements Serializable{
private Date stopDate;
private Date startDate;
private String carName;
private Integer carId;
private Integer userId; // Some userId from User.
}
These classes have their respective hbm.xml files. The underlying tables are un-related. Which means that I know that the userId in RentedCar is associated with the userId in User but there is no PK/FK relationship between them. I need to add a many-to-one association between RentedCar and User and one-to-many association between User and RentedCar. How should I do this in the hbm.xml files ?
These are the xml mappings:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="User" table="user">
<composite-id>
<key-property name="userName" column="user_name" type="string"/>
<key-property name="userParent" column="user_parent" type="string"/>
</composite-id>
<property name="userId" column="user_id" type="int"></property>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="RentedCar" table="rented_car">
<composite-id>
<key-property name="stopDate" column="stop_date" type="date" />
<key-property name="carId" column="car_id" type="int" />
<key-property name="userId" column="user_id" type="int" />
</composite-id>
<property name="startDate" column="start_date" type="date"></property>
<property name="carName" column="car_name" type="float"></property>
</class>
</hibernate-mapping>
I think you should have something in your classes show that there is one-to-many relationship in order to do this in hbm.xml files :
public class User implements Serializable{
private String userName;
private Integer userId;
private String userParent;
private Set<RentedCar> rentedCars;
}
public class RentedCar implements Serializable{
private Date stopDate;
private Date startDate;
private String carName;
private Integer carId;
private User user;
}
Then in RentedCar.hbm.xml you can inside use :
<many-to-one name="user" class="User">
<column name="userId" not-null="true"></column>
</many-to-one>
And in User.hbm.xml :
<set name="rentedCars" table="rented_car" fetch="select">
<key>
<column name="userId" not-null="true"></column>
</key>
<one-to-many class=" RentedCar "/>
</set>
This tutorial may help you http://www.tutorialspoint.com/hibernate/hibernate_one_to_many_mapping.htm

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 parent/child association. Update parent make child lost all associated objects

I have following classes.
public class Employee {
private int id;
private String firstName;
private String lastName;
private Address address;
private Employer employer;
}
public class Employer {
private int id;
private String name;
private Set<Employee> employees;
}
public class Address {
private int id;
}
public class Project{
private int id;
}
<hibernate-mapping>
<class name="me.hibernate.basic.xml.Employee" table="EMPLOYEE">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="firstName" column="first_name" type="string" />
<property name="lastName" column="last_name" type="string" />
<many-to-one name="address" column="address" unique="true" class="me.hibernate.basic.xml.Address"/>
<set name="projects" cascade="save-update, delete-orphan" sort="natural">
<key column="employee_proj_id" />
<one-to-many class="me.hibernate.basic.xml.Project" />
</set>
<many-to-one name="employer" column="employer" class="me.hibernate.basic.xml.Employer"/>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="me.hibernate.basic.xml.Employer" table="EMPLOYER">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" column="name" type="string" />
<set name="employees" cascade="save-update, delete-orphan" table="EMPLOYEE">
<key column="employer"/>
<one-to-many class="me.hibernate.basic.xml.Employee" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="me.hibernate.basic.xml.Address" table="ADDRESS">
<meta attribute="class-description"> This class contains the address detail. </meta>
<id name="id" type="int" column="id">
<generator class="native" />
</id>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="me.hibernate.basic.xml.Project" table="PROJECT">
<meta attribute="class-description"> This class contains the project detail. </meta>
<id name="id" type="int" column="id">
<generator class="native" />
</id>
</class>
</hibernate-mapping>
In my application I create few Employees and assign an address to them. And add some projects. Then I create an employer and add all the employees to employer. Once I add employees and update the employer, all the employees lose their addresses and projects. How can I do this with keeping lazy loading feature. I don't need to set lazy="false".
Employee emp1 = ME.addEmployee("Zara", "Ali");
Employee emp2 = ME.addEmployee("Daisy", "Das");
Address addr1 = ME.addAddress(35, "xxxxxx Street", "XXXXX", "XY7 0ZZ");
Address addr2 = ME.addAddress(42, "xxxxxx Street", "XXXXX", "XY7 7ZZ");
ME.setAddress(emp1.getId(), addr1);
ME.setAddress(emp2.getId(), addr2);
Set<Project> proj = new HashSet<Project>();
proj.add(new Project("NOVA"));
proj.add(new Project("GTA Simplify"));
proj.add(new Project("Jazz"));
ME.addProjects(emp.getId(), proj);
ME.addProjects(emp.getId(), proj);
All working up to this point.
Set<Employee> emps = new HashSet<Employee>();
emps.add(emp1); emps.add(emp2);
//Add existing employees to employer - Many-to-one bidirectional
Employer employer = ME.addEmployer("XYZ");
ME.addEmployees(employer.getId(), emps);
public Integer addEmployees(Integer employerID, Set<Employee> employees) {
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employer employer = (Employer) session.get(Employer.class,employerID);
employer.getEmployees().clear();
employer.getEmployees().addAll(employees);
session.update(employer);
tx.commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employerID;
}
Once I added employees, all the foreign key references are lost in the PROJECT.employee_proj_id and EMPLOYEE.address.
Hibernate log:
->Hibernate: update EMPLOYEE set first_name=?, last_name=?, basic=?, address=?, employer=? where id=?
->Hibernate: update EMPLOYEE set first_name=?, last_name=?, basic=?, address=?, employer=? where id=?
->Hibernate: update PROJECT set employee_proj_id=null where employee_proj_id=?
->Hibernate: update PROJECT set employee_proj_id=null where employee_proj_id=?
->Hibernate: update EMPLOYEE set employer=? where id=? ->Hibernate: update EMPLOYEE set employer=? where id=?
I see that you are clearing the employees before you add more employees, which is the root cause of everything. I'm not sure what you are doing when adding addresses, Project, employer etc., You need not clear the employees. If you have cascadetype.all set on the employees then saving the employer will update the newly added employees.
employer.getEmployees().clear();//remove this line.
employer.getEmployees().addAll(employees);

hibernate change the column name in a select

I have a table (node) with 3 data
- id(pk)
- question
- result
and 2 foreign key (many-to-one)
- LEFT_ID
- RIGHT_ID
here my hbm
<?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="com.beans.Nodes" table="node">
<id name="id" type="int" access="field">
<column name="id" />
<generator class="assigned" />
</id>
<property name="question" type="java.lang.String">
<column name="question" />
</property>
<property name="result" type="java.lang.String">
<column name="result" />
</property>
<many-to-one column="LEFT_ID" name="left" class="com.beans.Nodes" insert="false" update="false"></many-to-one>
<many-to-one column="RIGHT_ID" name="right" class="com.beans.Nodes" insert="false" update="false"></many-to-one>
</class>
</hibernate-mapping>
and my bean with getter/setter on LEFT/RIGHT_ID
#Entity
#Table (name = "node")
public class Nodes
{
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column (name = "question")
private String question;
#Column ( name = "result")
private String result;
private Nodes LEFT_ID;
private Nodes RIGHT_ID;
public Nodes getLeftNodes()
{
return LEFT_ID;
}
public void setLeftNodes(Nodes LEFT_ID)
{
this.LEFT_ID=LEFT_ID;
}
public Nodes getRightNodes()
{
return RIGHT_ID;
}
public void setRifhtNodes(Nodes right)
{
this.RIGHT_ID=right;
}
}
But when i deploy my project, i have this error
**Query: ReadAllQuery(referenceClass=Nodes sql="SELECT id, question, result, LEFT_ID_id, RIGHT_ID_id FROM node")**
When hibernate is a select, he change the name of the column. LEFT_ID becomes LEFT_ID_id and inevitably he finds nothing !
Why hibernate change the name of the LEFT_ID column ?
thanks

Categories

Resources