• 周六. 10 月 5th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Learning summary of Hibernate (5) — one to many cascade operation

King Wang

1 月 3, 2022

First of all, what is one to many , One-to-many relation It’s the relationship A relationship between two tables in a database , A single row in the first table in this relationship can be related to one or more rows in the second table , But a row in the second table can only be related to one row in the first table .

for example : I have one Customer Class represents a customer , One Linkman Class represents a contact . In this relationship , I define A customer Can correspond to Multiple contacts , and A contact person Can only For a customer , So the customer here is “ One ”, The contact person is “ many ”.

The principle of table building for one to many relationship : stay “ many ” The party creating the field as a foreign key , Point to “ One ” The primary key of the party .


For example, the example above , stay “ many ” Create a foreign key cid, Point to “ One ” On the side of . In the example, customer Zhang San has two contacts .


First, create two entity classes Customer Classes and Linkman class , Note that in these two classes you want to relate to each other

my Customer Class Set The way that sets are associated Linkman Class to represent that a customer can have multiple contacts

package com.hibernate.entity;
import java.util.HashSet;
import java.util.Set;
public class Customer {
// Customer id
private Integer cid;
// Name of customer
private String cName;
// Customer level
private String cLevel;
// Customer source
private String cSource;
// Customer contact number
private String cPhone;
// Customer email
private String cMail;
// Contacts
private Set<Linkman> linkmans = new HashSet<Linkman>();
public Set<Linkman> getLinkmans() {
return linkmans;
}
public void setLinkmans(Set<Linkman> linkmans) {
this.linkmans = linkmans;
}
public Integer getCid() {
return cid;
}
public String getcName() {
return cName;
}
public String getcLevel() {
return cLevel;
}
public String getcSource() {
return cSource;
}
public String getcPhone() {
return cPhone;
}
public String getcMail() {
return cMail;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public void setcName(String cName) {
this.cName = cName;
}
public void setcLevel(String cLevel) {
this.cLevel = cLevel;
}
public void setcSource(String cSource) {
this.cSource = cSource;
}
public void setcPhone(String cPhone) {
this.cPhone = cPhone;
}
public void setcMail(String cMail) {
this.cMail = cMail;
}
@Override
public String toString() {
return "Customer [cid=" + cid + ", cName=" + cName + ", cLevel=" + cLevel + ", cSource=" + cSource + ", cPhone="
+ cPhone + ", cMail=" + cMail + ", linkmans=" + linkmans + "]";
}
}
package com.hibernate.entity;
public class Linkman {
// Contacts id
private Integer lkm_id;
// Contact name
private String lkm_name;
// Contact gender
private String lkm_gender;
// Contact number
private String lkm_phone;
// Customers
private Customer lkm_customer;
public Customer getLkm_customer() {
return lkm_customer;
}
public void setLkm_customer(Customer lkm_customer) {
this.lkm_customer = lkm_customer;
}
public Integer getLkm_id() {
return lkm_id;
}
public String getLkm_name() {
return lkm_name;
}
public String getLkm_gender() {
return lkm_gender;
}
public String getLkm_phone() {
return lkm_phone;
}
public void setLkm_id(Integer lkm_id) {
this.lkm_id = lkm_id;
}
public void setLkm_name(String lkm_name) {
this.lkm_name = lkm_name;
}
public void setLkm_gender(String lkm_gender) {
this.lkm_gender = lkm_gender;
}
public void setLkm_phone(String lkm_phone) {
this.lkm_phone = lkm_phone;
}
@Override
public String toString() {
return "Linkman [lkm_id=" + lkm_id + ", lkm_name=" + lkm_name + ", lkm_gender=" + lkm_gender + ", lkm_phone="
+ lkm_phone + ", lkm_customer=" + lkm_customer + "]";
}
}

Entity class has , We can start to configure hibernate Object mapping file for , It is recommended to create an object mapping file with an entity class , Note that in the configuration here, we are going to do cascading configuration

Customer.hbm.xml The configuration of the file is as follows :

<?xml version="1.0" encoding="UTF-8"?>
<!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.hibernate.entity.Customer" table="hibernate_Customer">
<id name="cid" column="cid">
<generator class="native"></generator>
</id>
<property name="cName" column="cName"></property>
<property name="cLevel" column="cLevel"></property>
<property name="cSource" column="cSource"></property>
<property name="cPhone" column="cPhone"></property>
<property name="cMail" column="cMail"></property>
<!-- Represent all contacts in the customer mapping file -->
<!-- set Tags represent sets ,name Attribute is written to the customer entity class set The name of the collection -->
<set name="linkmans" cascade="save-update,delete">
<!-- One to many watch , There are foreign keys
hibernate Mechanism : Two way maintenance foreign key , That is to say “ many ” and “ One ”
Both sides need to configure foreign keys , Name the foreign key clid
-->
<key column="clid"></key>
<!-- One to many :class Write the full path of entity class in -->
<one-to-many class="com.hibernate.entity.Linkman"/>
</set>
</class>
</hibernate-mapping>

Linkman.hbm.xml The configuration of the file is as follows :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- Configuration classes correspond to tables
class
name: Entity class full pathname
table: Database table name
-->
<class name="com.hibernate.entity.Linkman" table="hibernate_Linkman">
<!-- Configure entity classes id And table id Corresponding
hibernate The entity class is required to have a property as a unique value
hibernate Require a field in the table as a unique value
-->
<!-- id label
name attribute : The entity class id The property name
column: Generated table field name
-->
<id name="lkm_id" column="lkm_id">
<!-- native: To generate table id Auto grow for primary key -->
<generator class="native"></generator>
</id>
<!-- property Label configuration entity class other properties -->
<property name="lkm_name" column="lkm_name"></property>
<property name="lkm_gender" column="lkm_gender"></property>
<property name="lkm_phone" column="lkm_phone"></property>
<!-- Indicates the customer to whom the contact belongs
name attribute : Means many to one “ One ”, This is the customer , Write lkm_customer name
class attribute :customer The full path
column attribute : Name of the foreign key
-->
<many-to-one name="lkm_customer" class="com.hibernate.entity.Customer" column="clid"></many-to-one>
</class>
</hibernate-mapping>

•    <many-to-one> Elements to map the constituent relationships

–  name: Set the name of the property of the persistent class to be mapped

–  column: Set the foreign key of the table corresponding to the property of the persistence class

–  class: Set the type of properties of the persistent class to be mapped

•    <set> Element to map the set Properties of type

–  name: Set the properties of the persistent class to be mapped

•    <key> Element sets the foreign key of the table corresponding to the associated persistence class

–  column: Specifies the foreign key name of the associated table

•    <one-to-many> Element sets the persistence class associated with the collection attribute

class: Specifies the class name of the associated persistence class

After the object mapping file is configured hibernate Core profile for hibernate.cfg.xml 了

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
<session-factory>
<!-- 1. Configuration database information -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/javadatabase</property>
<property name="connection.username">root</property>
<property name="connection.password">*******</property>
<!-- 2. To configure hibernate Information ( Optional ) -->
<!-- thread:Session Object's life cycle is bound to the local thread
jta:Session The life cycle of an object and JTA Transaction binding
managed:Hibernate Delegate to manage Session Object lifecycle -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- Output bottom layer sql sentence -->
<property name="show_sql">true</property>
<!-- Output bottom layer sql Sentence format -->
<property name="format_sql">true</property>
<!-- hibernate Help create tables , After configuration is needed
update: If the table already exists , Update , non-existent , Create
-->
<property name="hbm2ddl.auto">update</property>
<!-- Configure database dialect
stay MySQL It implements paging keywords limit, Only use MySQL in
stay oracle database , For page Publishing rownum
Give Way hibernate The framework identifies its own statements for different databases
-->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 3. Put the mapping file in the core configuration file -->
<mapping resource="Customer.hbm.xml"/>
<mapping resource="Linkman.hbm.xml"/>
</session-factory>
</hibernate-configuration>

Cascade operation :

    1. Cascade save :


In object

In the relationship mapping file
,
Elements used to map relationships between persistent classes
,<set>, <many-to-one>
and
<one-to-one>
There is one.
cascade
attribute
,
It specifies how to manipulate other objects associated with the current object

    Here I’ve configured <set> Labeled cascade Attribute to simplify , That is to say “ One ” The object mapping file of the party to configure

Corresponding to the above Customer.hbm.xml Medium save-update

<set name="linkmans" cascade="save-update,delete">

The test code is as follows :

// Simplify cascade saving , You need to configure “ One ” The object mapping file of one party is <set> Label configuration cascade The attribute is save-update
@Test
public void testSave(){
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// Create customer
Customer customer = new Customer();
customer.setcName(" Zhang San ");
customer.setcLevel("vip");
customer.setcSource(" Website ");
customer.setcPhone("13622222222");
customer.setcMail("[email protected]");
// Create a contact
Linkman linkman = new Linkman();
linkman.setLkm_name(" Wang Wu ");
linkman.setLkm_gender(" Woman ");
linkman.setLkm_phone("13678944321");
// Associate customers and contacts
customer.getLinkmans().add(linkman);
// preservation
session.save(customer);
tx.commit();
} catch (Exception e) {
tx.rollback();
}finally {
 session.close();
 }
}

After execution , You can find that two tables are created in the database

The information in the table is as follows :

Next let’s look at… In the console sql Statement output

First, two tables are created

And then to hibernate_Linkman Added foreign key pointing hibernate_Customer Of cid

Add data for two more tables

Finally hibernate_Linkman Foreign key assignment in

This is the whole process of creating and saving .

Cascade modification

Let’s first look at the data before modification in the database

Next we will contact Zhao Liu of Li Si , Change to Zhang San’s contact person

The test code is as follows

// Cascade modification
 @Test
 public void testUpdate(){
 Session session = null;
 Transaction tx = null;
 try {
 session = HibernateUtil.getSession();
 tx = session.beginTransaction();
 // according to id Get customers
 Customer customer = session.get(Customer.class, 1);
 // Get contacts
 Linkman linkman = session.get(Linkman.class, 2);
 // Modify persistent object to update database automatically
 customer.getLinkmans().add(linkman);
 linkman.setLkm_customer(customer);
 tx.commit();
 } catch (Exception e) {
 tx.rollback();
 }finally {
 session.close();
 }
 }

Now we find that the data in the database has changed

But now we see… In the console update Statement executed twice

Hibernate:
select
customer0_.cid as cid1_0_0_,
customer0_.cName as cName2_0_0_,
customer0_.cLevel as cLevel3_0_0_,
customer0_.cSource as cSource4_0_0_,
customer0_.cPhone as cPhone5_0_0_,
customer0_.cMail as cMail6_0_0_
from
hibernate_Customer customer0_
where
customer0_.cid=?
Hibernate:
select
linkman0_.lkm_id as lkm_id1_1_0_,
linkman0_.lkm_name as lkm_name2_1_0_,
linkman0_.lkm_gender as lkm_gend3_1_0_,
linkman0_.lkm_phone as lkm_phon4_1_0_,
linkman0_.clid as clid5_1_0_
from
hibernate_Linkman linkman0_
where
linkman0_.lkm_id=?
Hibernate:
select
linkmans0_.clid as clid5_1_0_,
linkmans0_.lkm_id as lkm_id1_1_0_,
linkmans0_.lkm_id as lkm_id1_1_1_,
linkmans0_.lkm_name as lkm_name2_1_1_,
linkmans0_.lkm_gender as lkm_gend3_1_1_,
linkmans0_.lkm_phone as lkm_phon4_1_1_,
linkmans0_.clid as clid5_1_1_
from
hibernate_Linkman linkmans0_
where
linkmans0_.clid=?
Hibernate:
update
hibernate_Linkman
set
lkm_name=?,
lkm_gender=?,
lkm_phone=?,
clid=?
where
lkm_id=?
Hibernate:
update
hibernate_Linkman
set
clid=?
where
lkm_id=?

This shows that the efficiency is not high , The same data was done twice update.

Here’s a brief introduction <set> Of inverse The attribute is


stay
hibernate
Through the right
inverse
Property to determine which side of the two-way Association maintains the relationship between tables
.
inverse = false
The active party ,
inverse= true
Of is the passive side
,
The active party is responsible for maintaining the relationship .
namely inverse = true To give up relationship maintenance ,false For not giving up relationship maintenance .

In no setting
inverse=true
Under the circumstances , Father and son both sides maintain father and son

  Relationship  

stay One to many In relationship , take “ many ” On the side of Setting the master controller will help improve performance

Next we configure , take Customer.hbm.xml Medium <set> add inverse The property value is true, namely Customer Give up relationship maintenance , And leave it to Linkman To maintain the relationship ( Because it’s not set inverse Property defaults to false)

<set name="linkmans" cascade="save-update,delete" inverse="true">

Then we will change back the database modification we just made .

@Test
public void testUpdate(){
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// according to id Get customers
Customer customer = session.get(Customer.class, 2);
// Get contacts
Linkman linkman = session.get(Linkman.class, 2);
// Modify persistent object to update database automatically
customer.getLinkmans().add(linkman);
linkman.setLkm_customer(customer);
tx.commit();
} catch (Exception e) {
tx.rollback();
}finally {
session.close();
}
}

You can see that the data has been modified back to the original value

Now the output in the console is as follows :

Hibernate:
select
customer0_.cid as cid1_0_0_,
customer0_.cName as cName2_0_0_,
customer0_.cLevel as cLevel3_0_0_,
customer0_.cSource as cSource4_0_0_,
customer0_.cPhone as cPhone5_0_0_,
customer0_.cMail as cMail6_0_0_
from
hibernate_Customer customer0_
where
customer0_.cid=?
Hibernate:
select
linkman0_.lkm_id as lkm_id1_1_0_,
linkman0_.lkm_name as lkm_name2_1_0_,
linkman0_.lkm_gender as lkm_gend3_1_0_,
linkman0_.lkm_phone as lkm_phon4_1_0_,
linkman0_.clid as clid5_1_0_
from
hibernate_Linkman linkman0_
where
linkman0_.lkm_id=?
Hibernate:
select
linkmans0_.clid as clid5_1_0_,
linkmans0_.lkm_id as lkm_id1_1_0_,
linkmans0_.lkm_id as lkm_id1_1_1_,
linkmans0_.lkm_name as lkm_name2_1_1_,
linkmans0_.lkm_gender as lkm_gend3_1_1_,
linkmans0_.lkm_phone as lkm_phon4_1_1_,
linkmans0_.clid as clid5_1_1_
from
hibernate_Linkman linkmans0_
where
linkmans0_.clid=?
Hibernate:
update
hibernate_Linkman
set
lkm_name=?,
lkm_gender=?,
lkm_phone=?,
clid=?
where
lkm_id=?

You can see update There is only one sentence , It improves efficiency .

cascading deletion

First look at the current data in the database

Next we delete the second customer, Li Si , Because the second customer Li Si’s contact person is Zhao Liu , So deleting Li Si will also delete Zhao Liu .

Now the output in the console is as follows :

// cascading deletion , stay “ One ” On the side of <set> Configuration in label cascade The attribute is delete( More than one value in English “,” separate )
@Test
public void testDelete(){
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// according to id Get customers
Customer customer = session.get(Customer.class, 2);
// Delete
session.delete(customer);
tx.commit();
} catch (Exception e) {
tx.rollback();
}finally {
session.close();
}
}

Database changes after execution

It was found that the second record of both tables was deleted .

Then let’s look at… In the console sql Statement output

Hibernate:
select
customer0_.cid as cid1_0_0_,
customer0_.cName as cName2_0_0_,
customer0_.cLevel as cLevel3_0_0_,
customer0_.cSource as cSource4_0_0_,
customer0_.cPhone as cPhone5_0_0_,
customer0_.cMail as cMail6_0_0_
from
hibernate_Customer customer0_
where
customer0_.cid=?
Hibernate:
select
linkmans0_.clid as clid5_1_0_,
linkmans0_.lkm_id as lkm_id1_1_0_,
linkmans0_.lkm_id as lkm_id1_1_1_,
linkmans0_.lkm_name as lkm_name2_1_1_,
linkmans0_.lkm_gender as lkm_gend3_1_1_,
linkmans0_.lkm_phone as lkm_phon4_1_1_,
linkmans0_.clid as clid5_1_1_
from
hibernate_Linkman linkmans0_
where
linkmans0_.clid=?
Hibernate:
delete
from
hibernate_Linkman
where
lkm_id=?
Hibernate:
delete
from
hibernate_Customer
where
cid=?

We found a detail ,hibernate First delete linkman Delete again customer. This is because linkman It contains a foreign key , If you delete customer, It’s possible linkman What the Central Plains point to customer There is no the , Then there is no logical correspondence , So the database doesn’t allow us to do this .

发表回复