Hibernate mapping error: duplicate foreign key - java

Entity Class UserExtraDetails with having one to one relationship with APP_USER with column SSO_ID
package com.eportal.models;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "userdetails")
public class userExtraDetails implements Serializable {
#Column(name = "Address", nullable = true)
private String Address;
#Id
#Column(name = "SSO_ID", nullable = false)
private String ssoId;
#Column(name = "City", nullable = true)
private String City;
#Column(name = "Country", nullable = true)
private String Country;
#Column(name = "Postal_Code", nullable = true)
private String Postal_Code;
#Column(name = "about_me", nullable = true)
private String about_me;
#OneToOne(fetch = FetchType.LAZY)
#JoinTable(name = "APP_USER", joinColumns = { #JoinColumn(name = "SSO_ID") })
private User user;
public String getAbout_me() {
return about_me;
}
public String getSsoId() {
return ssoId;
}
public void setSsoId(String ssoId) {
this.ssoId = ssoId;
}
public void setAbout_me(String about_me) {
this.about_me = about_me;
}
public String getAddress() {
return Address;
}
public void setAddress(String address) {
Address = address;
}
public String getCity() {
return City;
}
public void setCity(String city) {
City = city;
}
public String getCountry() {
return Country;
}
public void setCountry(String country) {
Country = country;
}
public String getPostal_Code() {
return Postal_Code;
}
public void setPostal_Code(String postal_Code) {
Postal_Code = postal_Code;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Entity Class User with a one to one relationship with userdetails with column SSO_ID
package com.eportal.models;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.validator.constraints.NotEmpty;
#Entity
#Table(name = "APP_USER")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotEmpty
#Column(name = "SSO_ID", unique = true, nullable = false)
private String ssoId;
#NotEmpty
#Column(name = "PASSWORD", nullable = false)
private String password;
#NotEmpty
#Column(name = "FIRST_NAME", nullable = false)
private String firstName;
#NotEmpty
#Column(name = "LAST_NAME", nullable = false)
private String lastName;
#NotEmpty
#Column(name = "EMAIL", nullable = false)
private String email;
#OneToOne(fetch = FetchType.LAZY)
#JoinTable(name = "userdetails", joinColumns = { #JoinColumn(name = "SSO_ID") })
private userExtraDetails details;
#NotEmpty
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "APP_USER_USER_PROFILE", joinColumns = { #JoinColumn(name = "USER_ID") }, inverseJoinColumns = {
#JoinColumn(name = "USER_PROFILE_ID") })
private Set<UserProfile> userProfiles = new HashSet<UserProfile>();
public userExtraDetails getDetails() {
return details;
}
public void setDetails(userExtraDetails details) {
this.details = details;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSsoId() {
return ssoId;
}
public void setSsoId(String ssoId) {
this.ssoId = ssoId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<UserProfile> getUserProfiles() {
return userProfiles;
}
public void setUserProfiles(Set<UserProfile> userProfiles) {
this.userProfiles = userProfiles;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((ssoId == null) ? 0 : ssoId.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof User))
return false;
User other = (User) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (ssoId == null) {
if (other.ssoId != null)
return false;
} else if (!ssoId.equals(other.ssoId))
return false;
return true;
}
/*
* DO-NOT-INCLUDE passwords in toString function. It is done here just for
* convenience purpose.
*/
#Override
public String toString() {
return "User [id=" + id + ", ssoId=" + ssoId + ", password=" + password + ", firstName=" + firstName
+ ", lastName=" + lastName + ", email=" + email + "]";
}
}
18:31:55.434 [localhost-startStop-1] ERROR o.h.tool.hbm2ddl.SchemaUpdate - HHH000388: Unsuccessful: alter table APP_USER add constraint FK_1wjx4w75wu94ftp6jvt35krf0 foreign key (user_id) references APP_USER
18:31:55.434 [localhost-startStop-1] ERROR o.h.tool.hbm2ddl.SchemaUpdate - There is already an object named 'FK_1wjx4w75wu94ftp6jvt35krf0' in the database.
18:31:55.438 [localhost-startStop-1] ERROR o.h.tool.hbm2ddl.SchemaUpdate - HHH000388: Unsuccessful: alter table APP_USER add constraint FK_hqk6uc88j3imq8u9jhro36vt3 foreign key (SSO_ID) references userdetails
18:31:55.438 [localhost-startStop-1] ERROR o.h.tool.hbm2ddl.SchemaUpdate - The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_hqk6uc88j3imq8u9jhro36vt3". The conflict occurred in database "CloudDB", table "dbo.userdetails", column 'SSO_ID'.
18:31:55.440 [localhost-startStop-1] ERROR o.h.tool.hbm2ddl.SchemaUpdate - HHH000388: Unsuccessful: alter table APP_USER_USER_PROFILE add constraint FK_brmce0t584euix4wb4rursf1q foreign key (USER_ID) references APP_USER
18:31:55.440 [localhost-startStop-1] ERROR o.h.tool.hbm2ddl.SchemaUpdate - There is already an object named 'FK_brmce0t584euix4wb4rursf1q' in the database.
18:31:55.442 [localhost-startStop-1] ERROR o.h.tool.hbm2ddl.SchemaUpdate - HHH000388: Unsuccessful: alter table userdetails add constraint FK_pffebqmeoi5qdq5g63w450h1i foreign key (SSO_ID) references APP_USER
18:31:55.442 [localhost-startStop-1] ERROR o.h.tool.hbm2ddl.SchemaUpdate - Column 'APP_USER.id' is not the same data type as referencing column 'userdetails.SSO_ID' in foreign key 'FK_pffebqmeoi5qdq5g63w450h1i'.
18:31:55.442 [localhost-startStop-1] INFO o.h.tool.hbm2ddl.SchemaUpdate - HHH000232: Schema update complete
The following error is shown:
Unsuccessful: alter table APP_USER add constraint
FK_1wjx4w75wu94ftp6jvt35krf0 foreign key (user_id) references APP_USER
There is already an object named 'FK_1wjx4w75wu94ftp6jvt35krf0' in the
database.
Unsuccessful: alter table APP_USER add constraint
FK_hqk6uc88j3imq8u9jhro36vt3 foreign key (SSO_ID) references
userdetails
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
"FK_hqk6uc88j3imq8u9jhro36vt3". The conflict occurred in database
"CloudDB", table "dbo.userdetails", column 'SSO_ID'.
Unsuccessful: alter table APP_USER_USER_PROFILE add constraint
FK_brmce0t584euix4wb4rursf1q foreign key (USER_ID) references APP_USER
There is already an object named 'FK_brmce0t584euix4wb4rursf1q' in the
database.
Unsuccessful: alter table userdetails add constraint
FK_pffebqmeoi5qdq5g63w450h1i foreign key (SSO_ID) references APP_USER
Column 'APP_USER.id' is not the same data type as referencing column
'userdetails.SSO_ID' in foreign key 'FK_pffebqmeoi5qdq5g63w450h1i'.

Related

Update using one to one relationship hibernate

I have one parent object as Employee and child object as Address. I just need to update the both objects using Employee object. But when updating using employee object i just getting emp_id should not be null. Here is my table and entity
CREATE TABLE `employee` (
`employee_id` bigint(20) NOT NULL AUTO_INCREMENT,
`employee_name` varchar(30) NOT NULL,
`employee_desg` varchar(30) NOT NULL,
`salary` varchar(30) NOT NULL,
`employee_reference_id` varchar(10) NOT NULL,
PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
Address table
CREATE TABLE `address` (
`address_id` bigint(20) NOT NULL AUTO_INCREMENT,
`emp_id` bigint(20) NOT NULL,
`address` varchar(255) NOT NULL,
PRIMARY KEY (`address_id`),
KEY `employee_address` (`emp_id`),
CONSTRAINT `employee_address` FOREIGN KEY (`emp_id`) REFERENCES `employee` (`employee_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
Employee Object
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "Employee")
public class Employee {
#Id
#GeneratedValue
#Column(name = "EMPLOYEE_ID")
private int id;
#Column(name = "EMPLOYEE_NAME")
private String employeeName;
#Column(name = "EMPLOYEE_DESG")
private String employeeDesg;
#Column(name = "SALARY")
private String salary;
#Column(name = "EMPLOYEE_REFERENCE_ID")
private String employeeReferenceId;
public String getEmployeeReferenceId() {
return employeeReferenceId;
}
public void setEmployeeReferenceId(String employeeReferenceId) {
this.employeeReferenceId = employeeReferenceId;
}
#OneToOne(mappedBy="employee", cascade = CascadeType.ALL)
private Address address;
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public String getEmployeeDesg() {
return employeeDesg;
}
public void setEmployeeDesg(String employeeDesg) {
this.employeeDesg = employeeDesg;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Address Object
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "ADDRESS")
public class Address {
#Id
#Column(name="ADDRESS_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name = "ADDRESS")
private String address;
#OneToOne(fetch=FetchType.EAGER , cascade=CascadeType.ALL, orphanRemoval=true)
#JoinColumn(name="emp_id",referencedColumnName="employee_id")
private Employee employee;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public Address() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
My code is
public class StudentUtil1To1 {
public static void main(String args[]){
SessionFactory factory=null;
Configuration configuration=null;
ServiceRegistry registry=null;
Session session=null;
try{
configuration= new Configuration();
configuration.configure();
registry=new StandardServiceRegistryBuilder().configure().applySettings(configuration.getProperties()).build();
factory=configuration.configure("hibernate.cfg.xml").buildSessionFactory(registry);
session= factory.openSession();
session.beginTransaction();
Employee emp=new Employee();
emp.setId(1);
emp.setEmployeeReferenceId("CP001");
emp.setEmployeeName("Muthu");
emp.setEmployeeDesg("Developer");
emp.setSalary("15000");
Address address=new Address();
address.setAddress("3, Civil aerodrome, CBE");
emp.setAddress(address);
address.setEmployee(emp);
session.update(emp);
System.out.println("Successfuly Saved");
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}finally{
if(session!=null){
session.close();
}
if(factory!=null){
factory.close();
}
}
}
}
And the error is
09:40:48.815 [http-nio-8081-exec-7] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 1048, SQLState: 23000
09:40:48.816 [http-nio-8081-exec-7] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Column 'emp_id' cannot be null
What i need to for update. Correct my mistake.
Since you have already mapped Address entity in employee entity like this
#OneToOne(mappedBy="employee", cascade = CascadeType.ALL)
private Address address;
You dont have to do same thing in address class means
#OneToOne(fetch=FetchType.EAGER , cascade=CascadeType.ALL, orphanRemoval=true)
#JoinColumn(name="emp_id",referencedColumnName="employee_id")
private Employee employee;
Above code is not required in address entity.And remove the employee attribute from address class.
Now you already added the CascadeType.ALL in OneToOne annotation and save only employee object like this
Employee emp=new Employee();
Address address=new Address("your address");
emp.setAddress(address);
emp.setId(1);
emp.setEmployeeReferenceId("CP001");
emp.setEmployeeName("Muthu");
emp.setEmployeeDesg("Developer");
emp.setSalary("15000");
session.update(emp);
1.#MapppedBy annotation means:the entity annotationed by #MapppedBy,give up the reference of key,so in the employee table,dont have the column named "address_id".
the relation between Employee and Address controlled by "address" table.
2. when you use [session.update(emp);],you havent have the data of "Employee" table.but emp_id is the FOREIGN KEY,so will occur this problem
3. i can first insert Employee,then [session.update(emp);]

#ManyToOne with JOIN FetchMode generating inner join

Reading all the documentation, using #Fetch(FetchMode.JOIN) on a #ManyToOne should by default I believe generate a left outer join, but for me it is always generating an inner join. These are my beans:
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
/**
* PensionMember entity. #author MyEclipse Persistence Tools
*/
#Entity
#Table(name = "Z_PENSION_MEMBERS", schema = "DANAOS")
public class PensionMember implements java.io.Serializable {
private static final long serialVersionUID = -4541446336298304689L;
// Fields
private Long id;
private Long personsCode;
private String employeeCode;
private String personType;
private CrewOfficeEmployee employee;
private PersonTO person;
// Property accessors
#Id
#Column(name = "ID", unique = true, nullable = false, precision = 0)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "EMPLOYEE_CODE", length = 12)
public String getEmployeeCode() {
return this.employeeCode;
}
public void setEmployeeCode(String employeeCode) {
this.employeeCode = employeeCode;
}
#ManyToOne( cascade = CascadeType.REFRESH, optional=true )
#JoinColumn( name = "EMPLOYEE_CODE", insertable = false, updatable = false )
#Fetch(FetchMode.JOIN)
public CrewOfficeEmployee getEmployee(){
return employee;
}
public void setEmployee( CrewOfficeEmployee employee ){
this.employee = employee;
}
#Column(name = "PERSONS_CODE", precision = 126, scale = 0, insertable = false, updatable = false)
public Long getPersonsCode() {
return this.personsCode;
}
public void setPersonsCode(Long personsCode) {
this.personsCode = personsCode;
}
#ManyToOne( cascade = CascadeType.REFRESH, optional=true )
#JoinColumn( name = "PERSONS_CODE" )
#Fetch(FetchMode.JOIN)
public PersonTO getPerson() {
return person;
}
public void setPerson(PersonTO person) {
this.person = person;
}
#Column(name = "PERSON_TYPE", nullable = false, length = 1)
public String getPersonType() {
return this.personType;
}
public void setPersonType(String personType) {
this.personType = personType;
}
}
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
/**
* CrewOfficeEmployee entity. #author MyEclipse Persistence Tools
*/
#Entity
#Table(name = "Z_CREW_OFFICE_EMPLOYEES", schema = "DANAOS")
public class CrewOfficeEmployee implements java.io.Serializable {
private static final long serialVersionUID = -5900130959401376537L;
// Fields
private String id;
private Integer crewOfficeJobTitleId;
private String name;
private String surname;
private Date dateOfBirth;
private Date effectiveJoiningDate;
private Date joiningDate;
private Date leavingDate;
// Property accessors
#Id
#Column(name = "ID", unique = true, nullable = false, length = 12)
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
#Column(name = "JOB_TITLE_ID", nullable = false)
public Integer getCrewOfficeJobTitleId() {
return crewOfficeJobTitleId;
}
public void setCrewOfficeJobTitleId(Integer crewOfficeJobTitleId) {
this.crewOfficeJobTitleId = crewOfficeJobTitleId;
}
#Column(name = "NAME", nullable = false, length = 30)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "SURNAME", nullable = false, length = 30)
public String getSurname() {
return this.surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
#Column(name = "DATE_OF_BIRTH", nullable = false, length = 7)
public Date getDateOfBirth() {
return this.dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
#Column(name = "EFFECTIVE_JOINING_DATE", nullable = false, length = 7)
public Date getEffectiveJoiningDate() {
return this.effectiveJoiningDate;
}
public void setEffectiveJoiningDate(Date effectiveJoiningDate) {
this.effectiveJoiningDate = effectiveJoiningDate;
}
#Column(name = "JOINING_DATE", nullable = false, length = 7)
public Date getJoiningDate() {
return this.joiningDate;
}
public void setJoiningDate(Date joiningDate) {
this.joiningDate = joiningDate;
}
#Column(name = "LEAVING_DATE", length = 7)
public Date getLeavingDate() {
return this.leavingDate;
}
public void setLeavingDate(Date leavingDate) {
this.leavingDate = leavingDate;
}
}
This is my query:
Criteria crit = getSession().createCriteria(PensionMember.class);
crit.createAlias("employee", "employee");
crit.createAlias("person", "person");
crit.add(
Restrictions.or(
Restrictions.and(
Restrictions.eq( PERSON_TYPE, "V" ),
Restrictions.like( "person.personsSurname", surname, MatchMode.START ).ignoreCase()
),
Restrictions.and(
Restrictions.eq( PERSON_TYPE, "O" ),
Restrictions.like( "employee.surname", surname, MatchMode.START ).ignoreCase()
)
)
);
... and this is the resulting SQL:
select * from ( select this_.ID as ID23020_6_, this_.EMPLOYEE_CODE as EMPLOYEE3_23020_6_, this_.PERSONS_CODE as PERSONS7_23020_6_,
this_.PERSON_TYPE as PERSON6_23020_6_, employee1_.ID as ID23010_0_, employee1_.JOB_TITLE_ID as JOB2_23010_0_,
employee1_.DATE_OF_BIRTH as DATE3_23010_0_, employee1_.EFFECTIVE_JOINING_DATE as EFFECTIVE4_23010_0_,
employee1_.JOINING_DATE as JOINING5_23010_0_, employee1_.LEAVING_DATE as LEAVING6_23010_0_,
employee1_.NAME as NAME23010_0_, employee1_.SURNAME as SURNAME23010_0_, person2_.STATUS_CODE as STATUS2_22758_1_, etc
from DANAOS.Z_PENSION_MEMBERS this_
inner join DANAOS.Z_CREW_OFFICE_EMPLOYEES employee1_ on this_.EMPLOYEE_CODE=employee1_.ID
inner join PERSONS person2_ on this_.PERSONS_CODE=person2_.PERSONS_CODE
where ((this_.PERSON_TYPE=? and lower(person2_.PERSONS_SURNAME) like ?) or
(this_.PERSON_TYPE=? and lower(employee1_.SURNAME) like ?)) ) where rownum <= ?
How come?! Can someone tell me what I'm doing wrong?
Thanks,
Neil
I'm using Hibernate 3.6.10 btw
Having realised it was the criteria query that was the problem, the solution was to change the createAlias() methods:
Criteria crit = getSession().createCriteria(PensionMember.class);
crit.createAlias("employee", "employee", CriteriaSpecification.LEFT_JOIN);
crit.createAlias("person", "person", CriteriaSpecification.LEFT_JOIN);
#ManyToOne( cascade = CascadeType.REFRESH, optional=true )
#JoinColumn( name = "EMPLOYEE_CODE", insertable = false, updatable = false )
#Fetch(FetchMode.JOIN)
public CrewOfficeEmployee getEmployee(){
return employee;
}
first of all change "insertable = false" to true.
I am getting(left outer join) :
Hibernate:
select this_.ID as ID1_1_1_, this_.EMPLOYEE_CODE1 as EMPLOYEE3_1_1_,
this_.EMPLOYEE_CODE as EMPLOYEE2_1_1_, crewoffice2_.ID as ID1_0_0_,
crewoffice2_.JOB_TITLE_ID as JOB_TITL2_0_0_,
crewoffice2_.DATE_OF_BIRTH as DATE_OF_3_0_0_,
crewoffice2_.EFFECTIVE_JOINING_DATE as EFFECTIV4_0_0_,
crewoffice2_.JOINING_DATE as JOINING_5_0_0_, crewoffice2_.LEAVING_DATE
as LEAVING_6_0_0_, crewoffice2_.NAME as NAME7_0_0_,
crewoffice2_.SURNAME as SURNAME8_0_0_ from Z_PENSION_MEMBERS this_
left outer join Z_CREW_OFFICE_EMPLOYEES crewoffice2_ on
this_.EMPLOYEE_CODE1=crewoffice2_.ID order by this_.ID asc
I think your code should work.

Issue in creating a Foreign Key relationship through Hibernate Annonations

I have 2 class Employee and Passport, then I tried to create a one to one mapping with Primary and Foreign Key Relationship with Annotations, but the foreign key relationship is not happening in Passport table.
Here Primary_Id is Emp_No in Employee table and must be a foreign Key in Passport table.
Below i have provided the 2 POJO classes for Employee and Passport and also the generated SQL from Hibernate.
Could somebody help me where I make mistake. Kindly let me know in case of further information.
Employee
package com.otr.hibernate;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
/**
*
* #author SPAR
*/
#Entity
public class Employee implements Serializable {
#Id
private String emp_No;
private String first_Name;
private String second_Name;
private String designation;
public String getEmp_No() {
return emp_No;
}
public void setEmp_No(String emp_No) {
this.emp_No = emp_No;
}
public String getFirst_Name() {
return first_Name;
}
public void setFirst_Name(String first_Name) {
this.first_Name = first_Name;
}
public String getSecond_Name() {
return second_Name;
}
public void setSecond_Name(String second_Name) {
this.second_Name = second_Name;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
}
Passport.java
package com.otr.hibernate;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
/**
*
* #author SPAR
*/
#Entity
public class Passport implements Serializable {
private String passport_No;
#Id #GeneratedValue(generator = "foreign")
#GenericGenerator(name= "foreign", strategy = "foreign", parameters = {#Parameter(value = "employee", name = "property")})
private String emp_RN_No;
#OneToOne (cascade = CascadeType.ALL)
#JoinColumn(name = "emp_RN_No")
private Employee employee;
public String getPassport_No() {
return passport_No;
}
public void setPassport_No(String passport_No) {
this.passport_No = passport_No;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getEmp_No() {
return emp_No;
}
public void setEmp_RN_No(String emp_No) {
this.emp_No = emp_No;
}
}
Hibernate Generation
Hibernate: create table Employee (emp_No varchar(255) not null, designation varchar(255), first_Name varchar(255), second_Name varchar(255), primary key (emp_No));
Hibernate: create table Passport (emp_No varchar(255) not null, passport_No varchar(255), primary key (emp_No));
You don't need the GenericGenerator to do that. There are two simpler alternatives:
Combine #Id and #OneToOne:
#Id #OneToOne (cascade = CascadeType.ALL)
#JoinColumn(name = "emp_RN_No")
private Employee employee;
Make sure you remove the previous #Id property emp_RN_No
Using #MapsId:
#Id
private String emp_RN_No;
#MapsId #OneToOne
#JoinColumn(name = "emp_RN_No")
private Employee employee;

Associating two tables with hibernate annotations

I am new to Hibernate, so please forgive me if the question is duplicated or stupid. I am using Hibernate 3.3.0, PostgreSQL DB. Right now I have 2 entities. I need to associate them with #OneToMany annotation in such way, that User.roleID was PK and Role.id was FK (user can have only one role, and the same role can be assigned to many users). Also as I was searching Google, I found out that for some reason every example with annotation associations has the annotated field declared as Set. Please, explain this to me. Thank you in advice.
Nazar.
User entity:
package com.dataart.mediaportal.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "users")
public class User implements Serializable {
private int id;
private String login;
private String password;
private String firstName;
private String lastName;
private int roleID;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id", unique = true)
public int getId() {
return id;
}
#Column(name = "user_login", nullable=false, unique = true, length = 20 )
public String getLogin() {
return login;
}
#Column(name = "user_password", nullable = false, length = 32)
public String getPassword() {
return password;
}
#Column(name = "user_name", nullable = true)
public String getFirstName() {
return firstName;
}
#Column(name = "user_lastname", nullable = true)
public String getLastName() {
return lastName;
}
#Column(name = "role_id", nullable = false)
public int getRoleID() {
return roleID;
}
public void setRoleID(int roleID) {
this.roleID = roleID;
}
public void setId(int id) {
this.id = id;
}
public void setLogin(String login) {
this.login = login;
}
public void setPassword(String password) {
this.password = password;
}
public void setFirstName(String firstname) {
this.firstName = firstname;
}
public void setLastName(String lastname) {
this.lastName = lastname;
}
}
Role entity:
package com.dataart.mediaportal.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "roles")
public class Role implements Serializable {
private int id;
private String role;
#Id
#Column(name = "role_id", nullable = false)
public int getId() {
return id;
}
#Column(name = "role_name", nullable = false)
public String getRole() {
return role;
}
public void setId(int id) {
this.id = id;
}
public void setRole(String role) {
this.role = role;
}
}
DB Script:
DROP TABLE IF EXISTS users CASCADE;
DROP TABLE IF EXISTS roles CASCADE;
DROP TABLE IF EXISTS albums CASCADE;
DROP TABLE IF EXISTS images CASCADE;
CREATE TABLE users
(
user_login character varying(20) NOT NULL,
user_password character varying(32) NOT NULL,
user_name character varying,
user_lastname character varying,
role_id integer DEFAULT 0,
user_id serial NOT NULL,
CONSTRAINT pk_user_id PRIMARY KEY (user_id),
CONSTRAINT users_user_login_key UNIQUE (user_login)
)
WITH (
OIDS=FALSE
);
ALTER TABLE users
OWNER TO postgres;
CREATE TABLE roles
(
role_id integer NOT NULL,
role_name character varying NOT NULL DEFAULT 'user'::character varying,
CONSTRAINT role_id_pk PRIMARY KEY (role_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE roles
OWNER TO postgres;
INSERT INTO roles
VALUES ( 0, 'user' ),
( 1, 'admin' );
-- testlog - testpass
-- user - password
INSERT INTO users
VALUES ( 'testlog', '179ad45c6ce2cb97cf1029e212046e81', 'Nazar', 'Sobchuk', 1),
('user', '5f4dcc3b5aa765d61d8327deb882cf99', 'unknown', 'unknown', 0);
CREATE TABLE albums
(
album_name character varying NOT NULL,
user_id integer,
album_id serial NOT NULL,
CONSTRAINT album_id PRIMARY KEY (album_id),
CONSTRAINT user_id FOREIGN KEY (user_id)
REFERENCES users (user_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE albums
OWNER TO postgres;
CREATE INDEX fki_user_id
ON albums
USING btree
(user_id);
INSERT INTO albums VALUES ('Main Album', 1);
CREATE TABLE images
(
img bytea,
img_name character varying NOT NULL,
album_id integer,
img_id serial NOT NULL,
CONSTRAINT images_img_name UNIQUE(img_name),
CONSTRAINT album_id FOREIGN KEY (album_id)
REFERENCES albums (album_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE images
OWNER TO postgres;
CREATE INDEX fki_album_id
ON images
USING btree
(album_id);
Insert user:
public boolean insertUser(User user) {
factory = getSessionFactory();
session = factory.openSession();
tx = session.beginTransaction();
Query queryResult = session.createQuery("from User");
List<User> userList = queryResult.list();
for (User u : userList) {
if (u.getLogin().equalsIgnoreCase(user.getLogin())) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("User_is_already_registered"));
return false;
}
}
session.save(user);
tx.commit();
session.close();
return true;
}
Add the user as one to many relationship to Role as below. create the setters as well
private List<User> userList;
#OneToMany(mappedBy = "role")
public List<User> getUserList() {
return userList;
}
Add the Role as many to one relationship to User as below
private Role role;
#ManyToOne
public Role getRole() {
return role;
}

Tomcat loadbalancing serialize exception PersistenceExceptionTranslationInterceptor : lazy initialization exception

I have to put two tomcat servers (tcat01 and tcat02) in a loadbalancing architecture.
I'm using tomcat 6.x and I edited the conf/server.xml like this on tomcat tcat01 :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tcat01">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"/>
....
On tcat02 conf/server.xml is like this :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tcat02">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"/>
....
I started tcat01, and then tcat02, il catalina.out it seems that tcat01 communicates well with tcat02.
Then I connected to the webapp with internet navigator, and then each time I do something in the webapp (I mean when I navigate) there is this exception :
Nov 24, 2011 12:00:13 AM org.apache.catalina.core.ContainerBase backgroundProcess
WARNING: Exception processing manager org.apache.catalina.ha.session.DeltaManager#278c4835 background process
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mycompany.myproject.model.authentification.Authority.groups, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:332)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
And here is the code of the class which cannot be sezialized (ie the java bean mentioned in the stack trace) :
import static javax.persistence.GenerationType.IDENTITY;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
#Entity
#Table(name = "authority", uniqueConstraints = #UniqueConstraint(columnNames = "name"))
public class Authority implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -7436593455923433675L;
//SYSTEM ROLE CONSTANT
public static final String MANAGER_SYSTEM_ROLE = "ROLE_MANAGER";
public static final String CLIENT_SYSTEM_ROLE = "ROLE_CLIENT";
public static final String PEDAGO_ADMIN_SYSTEM_ROLE = "ROLE_PEDAGO_ADMIN";
private Integer id;
#Size(min=1)
#Pattern(regexp="^ROLE[_a-zA-Z]+$", message="{authority.name.pattern.error}")
private String name;
#Size(max=65535)
private String description;
private Boolean isSystem;
private Set<Group> groups = new HashSet<Group>(0);
public Authority() {
this.isSystem = false;
}
public Authority(String name) {
this.name = name;
this.isSystem = false;
}
public Authority(String name, String description, Set<Group> groups) {
this.name = name;
this.description = description;
this.groups = groups;
this.isSystem = false;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name", unique = true, nullable = false, length = 45)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "description")
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public void setIsSystem(Boolean isSystem) {
this.isSystem = isSystem;
}
#Column(name = "system")
public Boolean getIsSystem() {
return isSystem;
}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "group_authorities", joinColumns = { #JoinColumn(name = "authority_id", nullable = false, updatable = true) }, inverseJoinColumns = { #JoinColumn(name = "group_id", nullable = false, updatable = true) })
public Set<Group> getGroups() {
return this.groups;
}
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
#PrePersist
protected void updateSystemField() {
if(isSystem == null)
isSystem = false;
}
}
And here is the code of the java bean Group (cause we have a lazily initialize exception on a collection of Groups) :
import static javax.persistence.GenerationType.IDENTITY;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
#Entity
#Table(name = "groups", uniqueConstraints = #UniqueConstraint(columnNames = "name"))
public class Group implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 7380068327050752558L;
private Integer id;
#NotNull
#Size(min=1)
private String name;
private String description;
private Boolean isSystem;
private Set<Authority> authorities = new HashSet<Authority>(0);
private Set<User> users = new HashSet<User>(0);
public Group() {
this.isSystem = false;
}
public Group(String name) {
this.name = name;
this.isSystem = false;
}
public Group(String name, String description, Set<Authority> authorities, Set<User> users) {
this.name = name;
this.description = description;
this.isSystem = false;
this.authorities = authorities;
this.users = users;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name", unique = true, nullable = false, length = 45)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "description")
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public void setIsSystem(Boolean isSystem) {
this.isSystem = isSystem;
}
#Column(name = "system")
public Boolean getIsSystem() {
return isSystem;
}
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "group_authorities", joinColumns = { #JoinColumn(name = "group_id", nullable = false, updatable = true) }, inverseJoinColumns = { #JoinColumn(name = "authority_id", nullable = false, updatable = true) })
public Set<Authority> getAuthorities() {
return this.authorities;
}
public void setAuthorities(Set<Authority> authorities) {
this.authorities = authorities;
}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "group_users", joinColumns = { #JoinColumn(name = "group_id", nullable = false, updatable = true) }, inverseJoinColumns = { #JoinColumn(name = "user_id", nullable = false, updatable = true) })
public Set<User> getUsers() {
return this.users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public void addAuthority(Authority authority) {
if(authorities == null)
authorities = new HashSet<Authority>(0);
authorities.add(authority);
}
public boolean removeAuthority(Authority authority) {
return authorities == null || authorities.remove(authority);
}
public void addUser(User user) {
if(users == null)
users = new HashSet<User>(0);
users.add(user);
}
public boolean removeUser(User user) {
return users == null || users.remove(user);
}
#PrePersist
protected void updateSystemField() {
if(isSystem == null)
isSystem = false;
}
}
Thanks for your help
You're getting the lazy instantiation exception since you have authority groups mapped as lazy. By the time the session is replicated, you're outside of an active session so it can't be hydrated. To remedy this, you have a few options:
Change your mapping so the association is fetched eagerly
Change your DAO to step into that collection (or use hibernate.initialize) to force the lazy load to occur before the session is closed
Detach the object from the session and then explicitly set the groups to null on the object before it is put into session to replace the hibernate proxy that is there.
For this particuar case, options 1 or 2 are probably the cleanest.

Categories