Ravi Nain Ravi Nain - 2 months ago 11
Java Question

Cascade is not working in Hibernate One-to-One mapping

Person.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="person")
public class Person {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

@Column(name="name")
private String name;

@Column(name="age")
private int age;

@OneToOne(mappedBy="person")
private Passport passport;

----getter and setter----


Passport.java

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
public class Passport {

@Id
private String passportNumber;
private Date issuedDate;
private Date expiryDate;
private String issuedPlace;
private String nationality;

@OneToOne
@Cascade(value={CascadeType.DELETE})
@JoinColumn(name="frn_person_id", unique=true, referencedColumnName="id")
private Person person;

---getter setter----


Hibernate Version: 4.2.0.Final

MySQL : 5.6.17


The above code generates SQL table like below:

CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`age` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

CREATE TABLE `passport` (
`passportNumber` varchar(255) NOT NULL,
`expiryDate` datetime DEFAULT NULL,
`issuedDate` datetime DEFAULT NULL,
`issuedPlace` varchar(255) DEFAULT NULL,
`nationality` varchar(255) DEFAULT NULL,
`frn_person_id` int(11) DEFAULT NULL,
PRIMARY KEY (`passportNumber`),
KEY `FK4C60F032382EC083` (`frn_person_id`),
CONSTRAINT `FK4C60F032382EC083` FOREIGN KEY (`frn_person_id`) REFERENCES `person` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


However, I want to generate tables like below:

create table jaydb.person(
id integer auto_increment primary key,
name varchar(100) unique,
age integer
);

create table jaydb.passport(
passport_number varchar(50) primary key,
issued_date date,
expiry_date date,
issued_place varchar(100),
nationality varchar(100),
frn_person_id integer unique,
foreign key(p_id)
references jaydb.person(p_id)
on delete cascade
on update cascade
);


As you can see the cascade code is missing from the hibernate's generated tables. My requirement is to setup One-to-One mapping between Person and Passport. If person data gets deleted then it's associated passport should be deleted as well.

I've tried javax.persistence cascade as well but it didn't work.

Answer

I believe that in your schema, the Person class is the owning relationship, as evidenced by that you have the mappedBy property on the passport which the person owns. As far as I know, the cascade annotation should be on the owning side of the relationship. However, you currently have it on the passport. Change your Person class to look like this:

@Entity
@Table(name="person")
public class Person {
    ...

    @OneToOne(mappedBy="person")
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
    private Passport passport;
    ...
}

And remove the @Cascade annotatiom from the Passport class.