Hibernate-one-way multiple-to-first-cascade removal issues

Source: Internet
Author: User
Tags generator

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.












Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.