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
.
The active party ,
inverse= true
Of is the passive side
,
The active party is responsible for maintaining the relationship .
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 .