Hibernate one-way many-to-one when cascading deletes, some problems occur.
The following simulates the problem I am experiencing:
This simulation with a previous simulation method has been, blog: http://blog.csdn.net/openjdk8/article/details/38424403
Simulation Scenario: There is a department table t_dept, position table t_position.
Requirements: When you delete a department table, the job table is deleted regardless of the data. Delete the job table and delete it directly .
1, Build table:
Build table:
T_dept:: Department table
T_position: Job Table
CREATE TABLE t_dept (dept_id INT PRIMARY KEY auto_increment, #部门Id dept_name VARCHAR) #部门名字 ) ; CREATE TABLE t_position (position_id INT PRIMARY KEY auto_increment, #职位Id position_name VARCHAR (45), #职位名字 dept_id INT, #外键 CONSTRAINT fk_dept_position FOREIGN KEY (dept_id) REFER Ences t_dept (dept_id));
2, entity class (with one-way many to one):
Dept.java
Package Org.jian.domain;import Javax.persistence.column;import Javax.persistence.entity;import Javax.persistence.generatedvalue;import Javax.persistence.id;import Javax.persistence.table;import Org.hibernate.annotations.GenericGenerator; @Entity @table (name = "T_dept") public class Dept {private int id;private String name, @Id @genericgenerator (name = "Generator", strategy = "increment") @GeneratedValue (generator = "generator") @ Column (name= "dept_id") public int getId () {return ID;} public void setId (int id) {this.id = ID;} @Column (name= "dept_name") public String GetName () {return name;} public void SetName (String name) {this.name = name;}}
Position.java
Package Org.jian.domain;import Javax.persistence.cascadetype;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.manytoone;import Javax.persistence.table;import org.hibernate.annotations.GenericGenerator; @Entity @table (name = "T_position") public class Position {private int id;private String name;private Dept Dept; @Id @genericgenerator (name = "Generator", Strat Egy = "increment") @GeneratedValue (generator = "generator") @Column (name= "position_id") public int getId () {return ID;} public void setId (int id) {this.id = ID;} @Column (name= "Position_name") public String GetName () {return name;} public void SetName (String name) {this.name = name;} @ManyToOne (targetentity = dept.class, fetch = fetchtype.lazy, cascade = {Cascadetype.all}) @JoinColumn (name = "dept_id") Public Dept getdept () {return Dept;} public void Setdept (Dept Dept{this.dept = dept;}}
3, test class:
Package Org.jian.domain;import Org.hibernate.session;import Org.hibernate.sessionfactory;import Org.hibernate.transaction;import Org.hibernate.cfg.annotationconfiguration;import Org.junit.AfterClass;import Org.junit.beforeclass;import Org.junit.test;public class Depttest {private static sessionfactory SF; @BeforeClass public static void Beforeclass () {SF = new annotationconfiguration (). Configure (). Buildsessionfactory () ; } @AfterClass public static void Afterclass () {sf.close (); }/** * System initialization, adding data * Software Department: Architect, software engineer, programmer * Finance Department: Accounting * Personnel: No data */@Test public void Testinit () {Session session = Sf.opensession (); Transaction tx = Session.begintransaction (); Dept D1 = new Dept (); D1.setname ("software Department"); Dept D2 = new Dept (); D2.setname ("Finance Department"); Dept d3 = new Dept (); D3.setname ("Personnel Department"); Position P1 = new Position (); P1.setname ("architect"); P1.setdept (D1); Position P2 = new Position (); P2.setname ("softEngineer "); P2.setdept (D1); Position p3 = new Position (); P3.setname ("programmer"); P3.setdept (D1); Position P4 = new Position (); P4.setname ("Accounting"); P4.setdept (D2); Session.save (D1); Session.save (D2); Session.save (D3); Session.save (p1); Session.save (p2); Session.save (p3); Session.save (p4); Tx.commit (); Session.close (); }/** * We try to delete the software department with Data */@Test public void TestDelDept1 () {Session session = Sf.opensession (); Transaction tx = Session.begintransaction (); Dept Dept = (Dept) session.get (Dept.class, 1); Session.delete (dept); Tx.commit (); Session.close (); }/** * Test only delete position (programmer) Do NOT delete department */@Test public void TestDelDept2 () {Session session = Sf.opensession () ; Transaction tx = Session.begintransaction (); Position Position = (Position) session.get (Position.class, 3);//Programmer ID 3 session.delete (Position); Tx.commit (); Session.close (); } }
Test the first method, see the green bar, console output:
Hibernate:select Max (dept_id) from T_depthibernate:select Max (position_id) from T_positionhibernate:insert to T_dept (Dept_name, dept_id) VALUES (?,?) Hibernate:insert into T_dept (dept_name, dept_id) VALUES (?,?) Hibernate:insert into T_dept (dept_name, dept_id) VALUES (?,?) Hibernate:insert into T_position (dept_id, Position_name, position_id) VALUES (?,?,?) Hibernate:insert into T_position (dept_id, Position_name, position_id) VALUES (?,?,?) Hibernate:insert into T_position (dept_id, Position_name, position_id) VALUES (?,?,?) Hibernate:insert into T_position (dept_id, Position_name, position_id) VALUES (?,?,?)
MySQL-Generated tables:
Test TestDelDept1 () method, see a disgusting red bar, and error, console output and JUnit are as follows:
Hibernate:select dept0_.dept_id as dept1_0_0_, dept0_.dept_name as dept2_0_0_ from T_dept dept0_ where dept0_.dept_id=? Hibernate:delete from T_dept where dept_id=?
The same is true of the test TestDelDept2 () method,
Hibernate:select position0_.position_id as position1_1_0_, position0_.dept_id as dept3_1_0_, Position0_.position_name As position2_1_0_ from T_position position0_ where position0_.position_id=? Hibernate:select dept0_.dept_id as dept1_0_0_, dept0_.dept_name as dept2_0_0_ from T_dept dept0_ where dept0_.dept_id=? Hibernate:delete from T_position where position_id=? Hibernate:delete from T_dept where dept_id=?
When I put the Position.java inside:
@ManyToOne (targetentity = dept.class, fetch = fetchtype.lazy, cascade = {Cascadetype.all})
Switch
@ManyToOne (targetentity = dept.class, fetch = Fetchtype.lazy)
When there is no error, you can successfully delete the following statement executed.
Hibernate:select position0_.position_id as position1_1_0_, position0_.dept_id as dept3_1_0_, Position0_.position_name As position2_1_0_ from T_position position0_ where position0_.position_id=? Hibernate:delete from T_position where position_id=?
From the above we can guess,
CascadeThe configuration is configured on which side, then the entity class performs the cascade update or delete.
In order to solve this problem, I went online to check a lot of information, and finally tried a way, that is to use bidirectional multi-pair one to configure.
So we need to change the Dept.java class:
Package Org.jian.domain;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.id;import Javax.persistence.onetomany;import Javax.persistence.table;import org.hibernate.annotations.GenericGenerator; @Entity @table (name = "T_dept") public Class Dept { private int id; private String name; private Set< position> positions = new hashset<position> (); @Id @GenericGenerator ( Name = "Generator", strategy = "increment") @GeneratedValue (generator = "generator") @Column (name= "dept_id") public int getId () { return id;& nbsp; } public void setId (int id) { this. id = id; } @Column (name= "Dept_name") public String getName () {& nbsp; return name; } public void SetName (String name) { this.name = name; } @OneToMany (mappedby = "Dept", Cascade = cascadetype.all, fetch = fetchtype.lazy) public set< Position> getpositions () { return positions; } public void Setpositions (set<position> positions) { this.positions = positions; } }
The test class changes the initialized code:
@Test public void Testinit () {Session session = Sf.opensession (); Transaction tx = Session.begintransaction (); Dept D1 = new Dept (); D1.setname ("software Department"); Dept D2 = new Dept (); D2.setname ("Finance Department"); Dept d3 = new Dept (); D3.setname ("Personnel Department"); Position P1 = new Position (); P1.setname ("architect"); P1.setdept (D1); Position P2 = new Position (); P2.setname ("software engineer"); P2.setdept (D1); Position p3 = new Position (); P3.setname ("programmer"); P3.setdept (D1); Position P4 = new Position (); P4.setname ("Accounting"); P4.setdept (D2); D1.getpositions (). Add (p1); D1.getpositions (). Add (p2); D1.getpositions (). Add (p3); D2.getpositions (). Add (p4); Session.save (D1); Session.save (D2); Session.save (D3); Session.save (p1); Session.save (p2); Session.save (p3); Session.save (p4); Tx.commit (); Session.close (); }
To test this method, the console output is as follows:
Hibernate:select Max (dept_id) from T_depthibernate:select Max (position_id) from T_positionhibernate:insert to T_dept (Dept_name, dept_id) VALUES (?,?) Hibernate:insert into T_position (dept_id, Position_name, position_id) VALUES (?,?,?) Hibernate:insert into T_position (dept_id, Position_name, position_id) VALUES (?,?,?) Hibernate:insert into T_position (dept_id, Position_name, position_id) VALUES (?,?,?) Hibernate:insert into T_dept (dept_name, dept_id) VALUES (?,?) Hibernate:insert into T_position (dept_id, Position_name, position_id) VALUES (?,?,?) Hibernate:insert into T_dept (dept_name, dept_id) VALUES (?,?)
Execute the TESTDELDEPT1 () method and see the green bar
Hibernate:select dept0_.dept_id as dept1_0_0_, dept0_.dept_name as dept2_0_0_ from T_dept dept0_ where dept0_.dept_id=? Hibernate:select positions0_.dept_id as dept3_0_1_, positions0_.position_id as position1_1_, positions0_.position_id As position1_1_0_, positions0_.dept_id as dept3_1_0_, positions0_.position_name as position2_1_0_ from T_position positions0_ where positions0_.dept_id=? Hibernate:delete from T_position where position_id=? Hibernate:delete from T_position where position_id=? Hibernate:delete from T_position where position_id=? Hibernate:delete from T_dept where dept_id=?
Cascade Delete was successfully implemented on the "one" side.
Regenerate table
Test the TestDelDept2 () method and see the green bar, console output:
Hibernate:select position0_.position_id as position1_1_0_, position0_.dept_id as dept3_1_0_, Position0_.position_name As position2_1_0_ from T_position position0_ where position0_.position_id=? Hibernate:delete from T_position where position_id=?
~ Comprehensive:
1, in a one-to-many (many-to-one) relationship, if an entity class is configured with the Cascade attribute (except set to ' None '), the entity class will perform cascading operations.
2, if you want to implement after "one" delete, "many" data delete, you must configure a one-to-many relationship. Many-to-one relationships are configured because requirements require that the department be returned at the same time as the position is queried. Together, it is a multi-pair (one-to-many) bidirectional association.