Scene Settings:
The State stipulates that a person can work only in one company, and a company may have many employees. We use this scenario to analyze one-to-many, many-to-two correlation mappings, depending on the object.
one, many-to-one one-way Association mappings 1, many-to-one one-way association mappings: for employees, his correspondence with company is a many-to-one relationship
Po object: Employee.java
public class Employee {public
int id;
public String name;
Public company Company;
Getter, setter Method
}
Company.java
public class Company {public
int id;
public String name;
Getter, setter Method
}
As programmers, we all know that in the design database to add a foreign key on the many-to-one side, we add a reference to the company class in the Employee class.
Mapping files: Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hib.domain">
<class name="com.hib.domain.Employee" table="employee">
<id name="id" type="int">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="company" column="company_id"/>
</class>
</hibernate-mapping>
Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hib.domain.Company" table="company">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
Test:
@Test
public void testSaveCompany () {
Session session = HibernateUtils.getSession ();
Transaction tx = session.beginTransaction ();
Company company = new Company ();
company.setName ("XX Group");
session.save (company); // Here you must save the company first and make it persistent, otherwise it will report an error because it cannot save the transient object.
Employee employee1 = new Employee ();
employee1.setName ("Passerby A");
employee1.setCompany (company);
Employee employee2 = new Employee ();
employee2.setName ("Passenger B");
employee2.setCompany (company);
session.save (employee1);
session.save (employee2);
tx.commit ();
session.close ();
}
result:
It is worth mentioning that if we did not execute session.save (company) directly in the test program, we will report an error, but the solution is by no means the only one, we can also use the <many in the employee Employee mapping file Configure the cascade attribute in -to-one />:
<? xml version = "1.0" encoding = "UTF-8"?>
<! DOCTYPE hibernate-mapping PUBLIC
"-// Hibernate / Hibernate Mapping DTD 3.0 // EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package = "com.hib.domain">
<class name = "com.hib.domain.Employee" table = "employee">
<id name = "id" type = "int">
<generator class = "native" />
</ id>
<property name = "name" />
<many-to-one name = "company" column = "company_id" cascade = "save-update" />
</ class>
</ hibernate-mapping>
@Test
public void testSaveCompany () {
Session session = HibernateUtils.getSession ();
Transaction tx = session.beginTransaction ();
Company company = new Company ();
company.setName ("XX Group");
// session.save (company); // Here you must save company first and make it persistent, otherwise it will report an error because it cannot save the transient object
Employee employee1 = new Employee ();
employee1.setName ("Passerby A");
employee1.setCompany (company);
Employee employee2 = new Employee ();
employee2.setName ("Passenger B");
employee2.setCompany (company);
session.save (employee1);
session.save (employee2);
tx.commit ();
session.close ();
}
Some property values on cascade are: persist, merge, delete, save-update, evict, replicate, lock, refresh
Second, one-to-many,
one-way association mapping is also applicable to the above scenario setting: the state stipulates that an employee can only work in one company, but a company can have many employees. At this time, for the company, it is a one-to-many relationship. At such times, we need to add a collection of employee objects to the company class. This collection can be the relevant container of the set, list, map, array array (where the objects in the set are non-repeatable and the relative performance is high, it is recommended to use set)
Po object: Employee.java
public class Employee {
public int id;
public String name;
//getter, setter方法
}
Company.java
public class Company {
public int id;
public String name;
public Set<Employee> employees;
//getter, setter method
}
Mapping file: Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hib.domain">
<class name="com.hib.domain.Employee" table="employee">
<id name="id" type="int">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
Company.hbm.xml
<? xml version = "1.0" encoding = "UTF-8"?>
<! DOCTYPE hibernate-mapping PUBLIC
"-// Hibernate / Hibernate Mapping DTD 3.0 // EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "com.hib.domain.Company" table = "company">
<id name = "id">
<generator class = "native" />
</ id>
<property name = "name" />
<set name = "employees">
<key column = "company_id" /> <!-The "multi" party associates the "one" foreign key->
<one-to-many class = "com.hib.domain.Employee" /> <!-A Company object corresponds to multiple Employee objects->
</ set>
</ class>
</ hibernate-mapping>
Test:
@Test
public void testSaveCompany () {
Session session = HibernateUtils.getSession ();
Transaction tx = session.beginTransaction ();
Employee employee1 = new Employee ();
employee1.setName ("Passerby A");
session.save (employee1);
Employee employee2 = new Employee ();
employee2.setName ("Passenger B");
session.save (employee2);
Set <Employee> employees = new HashSet <> ();
employees.add (employee1);
employees.add (employee2);
Company company = new Company ();
company.setName ("XX Group");
company.setEmployees (employees);
session.save (company);
tx.commit ();
session.close ();
}
After the data is inserted, we query:
@Test
public void testQueryCompany () {
Session session = HibernateUtils.getSession ();
Transaction tx = session.beginTransaction ();
Company company = session.load (Company.class, 1);
System.out.println ("Company Name:" + company.getName ());
System.out.println ("Company employee:");
for (Employee employee: company.getEmployees ()) {
System.out.print ("" + employee.getName ());
}
tx.commit ();
session.close ();
}
search result:
Hibernate: select company0_.id as id1_0_0_, company0_.name as name2_0_0_ from company company0_ where company0_.id =?
Company Name: XX Group
workers:
Hibernate: select employees0_.company_id as company_3_1_0_, employees0_.id as id1_1_0_, employees0_.id as id1_1_1_, employees0_.name as name2_1_1_ from employee employees0_ where employees0_.company_id =?
Passerby B Passerby A
From the console message, lazy loading can also be delayed. If we change the configuration file to:
Company.hbm.xml
<? xml version = "1.0" encoding = "UTF-8"?>
<! DOCTYPE hibernate-mapping PUBLIC
"-// Hibernate / Hibernate Mapping DTD 3.0 // EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "com.hib.domain.Company" table = "company">
<id name = "id">
<generator class = "native" />
</ id>
<property name = "name" />
<set name = "employees" lazy = "false"> <!-If lazy is set to false here, lazy loading will be disabled. The default is true->
<key column = "company_id" /> <!-The "multi" party associates the "one" foreign key->
<one-to-many class = "com.hib.domain.Employee" /> <!-A Company object corresponds to multiple Employee objects->
</ set>
</ class>
</ hibernate-mapping>
search result:
Hibernate: select company0_.id as id1_0_0_, company0_.name as name2_0_0_ from company company0_ where company0_.id =?
Hibernate: select employees0_.company_id as company_3_1_0_, employees0_.id as id1_1_0_, employees0_.id as id1_1_1_, employees0_.name as name2_1_1_ from employee employees0_ where employees0_.company_id =?
Company Name: XX Group
workers:
Passerby A Passerby B
Third, many-to-one / one-to-many two-way association mapping
Now we still use the above scenario settings to achieve one-to-many / many-to-one two-way association:
Po object: Company.java
public class Company {
public int id;
public String name;
public Set<Employee> employees;
//getter, setter method
}
Employee.java
public class Employee {
public int id;
public String name;
public Company company;
//getter, setter method
}
Configuration file: Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hib.domain">
<class name="com.hib.domain.Employee" table="employee">
<id name="id" type="int">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="company" column="company_id" not-null="true"/>
</class>
</hibernate-mapping>
Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hib.domain.Company" table="company">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="employees">
<key column="company_id"/>
<one-to-many class="com.hib.domain.Employee"/>
</set>
</class>
</hibernate-mapping>
If you use a List (or other ordered collection class), you need to set the key column corresponding to the foreign key to not null, and let Hibernate manage the association from the collection side, maintaining the index of each element (by setting update = "false" and insert = "false" to reverse the operation on the other end):
Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hib.domain">
<class name="com.hib.domain.Employee" table="employee">
<id name="id" type="int">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="company" column="company_id" not-null="true" insert="false" update="false"/>
</class>
</hibernate-mapping>
Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hib.domain.Company" table="company">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="employees">
<key column="company_id" not-null="true"/>
<one-to-many class="com.hib.domain.Employee"/>
</set>
</class>
</hibernate-mapping>
If the underlying foreign key field corresponding to the <key> element of the collection map is NOT NULL, then it is important to define not-null = "true" for this key element. Don't just define not-null = "true" for possible nested <column> elements, the <key> element is also required.
Fourth, summary
1. For unidirectional one-to-many and many-to-one association mapping, when building a table, a foreign key is added to the "many" end to point to the "one" end. The difference between them is the difference in maintaining relationships. It can also be understood that the master table changes, and the relationship from whom to whom changes.
2. For two-way one-to-many / many-to-one, they are mutually oriented. Just pay attention to the different methods we need to configure for different places. When using set and list, they are roughly the same. The key is that when using list, the many-to-one slave table cannot be added by itself, and the primary / foreign key id of the one-to-many slave table cannot be empty
From: http://www.cnblogs.com/DoubleEggs/p/6257644.html