HIBERNATE知识复习记录3-关联关系

时间:2021-06-18 20:35:06

  先上一张图,关于几种关系映射:

  HIBERNATE知识复习记录3-关联关系

  抄一段解释:

  基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用。关联关系分为上述七种,但是由于相互之间有各种关系,可以简化,例如:多对一与一对多映射,只是侧重的角度不对而已。

  Hibernate将关系映射分为以上四种,现在来看关系映射其实就两种,甚至一种。

  1、从对象的加载方向上分为单向和双向两种。

   单向和双向只影响数据的加载,并不影响数据的存储。不论是一对一,一对多还是多对多,单向和双向生成的数据库表是一样,单向和双向的不同是由对象模型决定的。

  2、从对象的映射关系上分为一对多和多对一两种,它们又是从不同角度说的,所以也可以说是一种。

   一对一关联映射是多对一关联映射的特例,只是在“多”的一端加上唯一的限制之后,用来表示一对一的关联关系。

   多对多关联映射是一对多关联映射的特例,它们呢都是使用集合来表示多的关系,用<key>标签定义当前表的主键。

  以上是从SSH:Hibernate框架(七种关联关系映射及配置详解)摘抄下来的,具体内容可以看这篇文章。

  好了,下面复习一下我以前的学习内容吧。

  先说一说一对一关系。

  1-1,外键关联:

  部门与部门经理,一个部门对应一个部门经理。

  Department类

package onetoone.primary;

public class Department {
private Integer deptId;
private String deptName;
private Manager mgr;
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Manager getMgr() {
return mgr;
}
public void setMgr(Manager mgr) {
this.mgr = mgr;
}
}

  Manager类

package onetoone.primary;

public class Manager {
private Integer mgrId;
private String mgrName;
private Department dept;
public Integer getMgrId() {
return mgrId;
}
public void setMgrId(Integer mgrId) {
this.mgrId = mgrId;
}
public String getMgrName() {
return mgrName;
}
public void setMgrName(String mgrName) {
this.mgrName = mgrName;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
}

  Department.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 9:47:29 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="onetoone.foreign">
<class name="Department" table="DEPARTMENT">
<id name="deptId" type="java.lang.Integer">
<column name="DEPT_ID" />
<generator class="native" />
</id>
<property name="deptName" type="java.lang.String">
<column name="DEPT_NAME" />
</property> <!-- 使用many-to-one 的方式来映射1-1关联关系 -->
<many-to-one name="mgr" class="Manager" column="MGR_ID" unique="true"></many-to-one>
</class>
</hibernate-mapping>

  Manager.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 9:47:29 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="onetoone.foreign">
<class name="Manager" table="MANAGER">
<id name="mgrId" type="java.lang.Integer">
<column name="MGR_ID" />
<generator class="native" />
</id>
<property name="mgrName" type="java.lang.String">
<column name="MGR_NAME" />
</property> <!-- 映射1-1的关联关系:在对应的数据表中已经有外键了,当前持久化为使用one-to-one进行映射
没有外键的一端需要使用one-to-one元素,该元素使用property-ref属性指定使用被关联实体主键以外的字段作为关联字段
-->
<one-to-one name="dept" class="Department" property-ref="mgr"></one-to-one> </class> </hibernate-mapping>

  这里是双向的外键关联,生成的部门表中会有一个经理表的外键,双向还是单向对数据模型并没有影响,影响的是对象模型。单向的外键关联可以看我上面提供的链接。

  HibernateTest类

package onetoone.primary;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; public class HibernateTest {
private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before
public void init()
{
System.out.println("init"); // 1. 创建一个SessionFactory对象
sessionFactory = null;
Configuration configuration = new Configuration().configure(); // before 4.0
// sessionFactory = configuration.buildSessionFactory(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
// 2. 创建一个Session 对象
session = sessionFactory.openSession(); // 3. 开启事务
transaction = session.beginTransaction(); } @After
public void destory()
{
System.out.println("destory");
// 5. 提交事务
transaction.commit(); // 6. 关闭Session
session.close(); // 7. 关闭SesssionFactory
sessionFactory.close();
} @Test
public void testSave()
{
Department department = new Department();
department.setDeptName("DEPT-BB"); Manager manager = new Manager();
manager.setMgrName("MGR-BB"); department.setMgr(manager);
manager.setDept(department); // 建议先保存没有外键列的那个对象,这样会减少UPDATE语句
session.save(manager);
session.save(department);
} @Test
public void testGet()
{
//1. 默认情况下对关联属性使用懒加载,可能会出现懒加载异常
Department dept = (Department) session.get(Department.class, 1);
System.out.println(dept.getDeptName()); //3. 查询Manager对象的连接条件应该是dept.manager_id=mgr.manager_id
// 而不应该是dept.dept_id = mgr.manager_id
Manager mgr = dept.getMgr();
System.out.println(mgr.getMgrName()); } @Test
public void testGet2()
{
// 在查询没有外键的实体对象时,使用的左外连接查询,一并查询出关联的对象,并已经进行初始化
Manager mgr = (Manager)session.get(Manager.class, 1);
System.out.println(mgr.getMgrName());
}
}

  1-1,主键关联:

  Department类:

package onetoone.primarykey;

public class Department {
private Integer deptId;
private String deptName;
private Manager mgr;
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Manager getMgr() {
return mgr;
}
public void setMgr(Manager mgr) {
this.mgr = mgr;
}
}

  Manager类:

package onetoone.primarykey;

public class Manager {
private Integer mgrId;
private String mgrName;
private Department dept;
public Integer getMgrId() {
return mgrId;
}
public void setMgrId(Integer mgrId) {
this.mgrId = mgrId;
}
public String getMgrName() {
return mgrName;
}
public void setMgrName(String mgrName) {
this.mgrName = mgrName;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
}

  Department.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 9:47:29 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="onetoone.primary">
<class name="Department" table="DEPARTMENT">
<id name="deptId" type="java.lang.Integer">
<!-- 使用外键的方式来生成当前的主键 -->
<generator class="foreign">
<!-- property 属性指这使用当前持久化类的哪一个属性的主键作为外键 -->
<param name="property">mgr</param>
</generator>
</id>
<property generated="never" lazy="false" name="deptName" type="java.lang.String">
<column name="DEPT_NAME"/>
</property>
<!-- 采用主键生成策略的一端增加one-to-one元素映射关联属性,
其 one-to-one 属性还应增加constrained="true"属性,以使当前主键增加外键约束
    constrained="true"在新增或删除记录时会同时操作关联表
-->
<one-to-one class="Manager" name="mgr" constrained="true"/>
</class>
</hibernate-mapping>

  Manager.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 9:47:29 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="onetoone.primary">
<class name="Manager" table="MANAGER">
<id name="mgrId" type="java.lang.Integer">
<column name="MGR_ID"/>
<generator class="native"/>
</id>
<property generated="never" lazy="false" name="mgrName" type="java.lang.String">
<column name="MGR_NAME"/>
</property>
<!-- 怎么加载对象,抓取策略:join联合查询(默认),select:一条条的查询 -->
<one-to-one class="Department" name="dept" fetch="join" />
</class>
</hibernate-mapping>

  这里采用的是双向一对一主键生成策略,单向的一对一主键生成策略可以查看上面提供的文章。

  HibernateTest类

package onetoone.primarykey;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; public class HibernateTest {
private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before
public void init()
{
System.out.println("init"); // 1. 创建一个SessionFactory对象
sessionFactory = null;
Configuration configuration = new Configuration().configure(); // before 4.0
// sessionFactory = configuration.buildSessionFactory(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
// 2. 创建一个Session 对象
session = sessionFactory.openSession(); // 3. 开启事务
transaction = session.beginTransaction(); } @After
public void destory()
{
System.out.println("destory");
// 5. 提交事务
transaction.commit(); // 6. 关闭Session
session.close(); // 7. 关闭SesssionFactory
sessionFactory.close();
} @Test
public void testSave()
{
Department department = new Department();
department.setDeptName("DEPT-BB"); Manager manager = new Manager();
manager.setMgrName("MGR-BB"); department.setMgr(manager);
manager.setDept(department); // 先插入哪一个都不会有多余的update
session.save(department);
session.save(manager);
} @Test
public void testGet()
{
//1. 默认情况下对关联属性使用懒加载,可以会出现懒加载异常
Department dept = (Department) session.get(Department.class, 1);
System.out.println(dept.getDeptName()); //3. 查询Manager对象的连接条件应该是dept.manager_id=mgr.manager_id
// 而不应该是dept.dept_id = mgr.manager_id
Manager mgr = dept.getMgr();
System.out.println(mgr.getMgrName()); } @Test
public void testGet2()
{
// 在查询没有外键的实体对象时,使用的左外连接查询,一并查询出关联的对象,并已经进行初始化
Manager mgr = (Manager)session.get(Manager.class, 1);
System.out.println(mgr.getMgrName());
}
}

  再说说多对一。

  N-1关联:

  顾客和订单,一个顾客对应多个订单。

    单向N-1:

  Custom类

package ntoone;

public class Customer {
private int customerId;
private String customerName; public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
}

  Order类

package ntoone;

public class Order {
private int orderId;
private String orderName;
private Customer customer; public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}

  Customer.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-22 15:13:00 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="ntoone.Customer" table="CUSTOMER">
<id name="customerId" type="int">
<column name="CUSTOMER_ID" />
<generator class="native" />
</id>
<property name="customerName" type="java.lang.String">
<column name="CUSTOMER_NAME" />
</property>
</class>
</hibernate-mapping>

  Order.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-22 15:13:00 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="ntoone">
<class name="Order" table="ORDER">
<id name="orderId" type="int">
<column name="ORDER_ID" />
<generator class="native" />
</id>
<property name="orderName" type="java.lang.String">
<column name="ORDER_NAME" />
</property> <!-- 映射多对一的关联关系,使用many-to-one来映射多对一一关联关系
name:多这一端的一那一端的属性的名字
class:一那一端的属性对应的类名
column:一那一端在多的一端对应的数据表中的外键的名字
-->
<many-to-one name="customer" class="Customer" column="CUSTOMER_ID">
</many-to-one>
</class>
</hibernate-mapping>

  多的一端维护关联关系。想起一个故事,为什么要用多的一端维护关联关系,就好像一个部门里的人,有一个经理和很多职员,让经理记住每个职员的名字很难,但让职员记住经理的名字就很容易,这就是为什么单向多对一要让多的一端维护关联关系。

  HibernateTest类

package ntoone;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; public class HibernateTest {
private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before
public void init()
{
System.out.println("init"); // 1. 创建一个SessionFactory对象
sessionFactory = null;
Configuration configuration = new Configuration().configure(); // before 4.0
// sessionFactory = configuration.buildSessionFactory(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
// 2. 创建一个Session 对象
session = sessionFactory.openSession(); // 3. 开启事务
transaction = session.beginTransaction(); } @After
public void destory()
{
System.out.println("destory");
// 5. 提交事务
transaction.commit(); // 6. 关闭Session
session.close(); // 7. 关闭SesssionFactory
sessionFactory.close();
} @Test
public void testManyToOne()
{
Customer customer = new Customer();
customer.setCustomerName("BB"); Order order1 = new Order();
order1.setOrderName("order-3"); Order order2 = new Order();
order2.setOrderName("order-4"); // 设定关联关系
order1.setCustomer(customer);
order2.setCustomer(customer); // 执行save操作:先插入Customer, 再插入Order, 3条insert
// 先插入1的一端,再插入n的一端,只有insert语句
// session.save(customer);
// session.save(order1);
// session.save(order2); // 插入多的一端后,再插入一的一端,此时要更新多的一端的customerId,影响效率
session.save(order1);
session.save(order2);
session.save(customer);
} /**
* 1. 若查询多的一端的一个对象,则默认情况下只查询了多的一端的对象,而没有查询关联的一的那
* 一端的对象(延迟加载)
* 2. 在需要使用到关联的对象时,才发送对应的SQL语句
* 3. 在查询Customer对象时,由多一端导航到1的一端时,若
* session已经被关闭,会
* 发生懒加载异常
* 4. 获取Order对象时默认情况下,其关联的Customer对象是一个
* 代理对象
*/
@Test
public void testMany2OneGet()
{
Order order = (Order) session.get(Order.class, 1);
System.out.println(order.getOrderName()); System.out.println(order.getCustomer().getClass());
session.close(); Customer customer = order.getCustomer();
System.out.println(customer.getCustomerName());
} @Test
public void testUpdate()
{
Order order = (Order)session.get(Order.class, 1);
order.getCustomer().setCustomerName("AAA");
} public void testDelete()
{
// 在不设定级联关系的情况下,1这一端的对象有多的一端的对象在引用,
// 不能直接删除1的一端的对象
Customer customer = (Customer)session.get(Customer.class, 1);
session.delete(customer);
}
}

    双向N-1:

  Customer类:

package ntoone.both;

import java.util.HashSet;
import java.util.Set; public class Customer {
private int customerId;
private String customerName; /**
* 1.需要把集合进行初始化,防止出现空指针异常
* 2.声明集合类型时需使用接口类型,因为hibernate在获取
* 集合类型时,返回的是Hibernate内置的集合类型,而不是javaSE
* 一个标准的集合实现
*/
private Set<Order> orders = new HashSet<Order>(); public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
}

  Order类:

package ntoone.both;

public class Order {
private int orderId;
private String orderName;
private Customer customer; public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}

  Customer.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-22 16:58:35 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="ntoone.both">
<class name="Customer" table="CUSTOMER">
<id name="customerId" type="int">
<column name="CUSTOMER_ID" />
<generator class="native" />
</id>
<property name="customerName" type="java.lang.String">
<column name="CUSTOMER_NAME" />
</property>
<set name="orders" table="ORDER" inverse="true" cascade="save-update" order-by="ORDER_NAME DESC">
<key>
<column name="CUSTOMER_ID" />
</key>
<one-to-many class="Order" />
</set>
</class>
</hibernate-mapping>

  Order.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-22 16:58:35 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="ntoone.both">
<class name="Order" table="ORDER">
<id name="orderId" type="int">
<column name="ORDER_ID" />
<generator class="native" />
</id>
<property name="orderName" type="java.lang.String">
<column name="ORDER_NAME" />
</property>
<many-to-one name="customer" class="Customer" column="CUSTOMER_ID">
</many-to-one>
</class>
</hibernate-mapping>

  这是双向一对多关联,一的一端通过指定自身的键值确定关联的多的一端,多的一端通过一的一端的键值确定关联的一的一端。

  HibernateTest类

package ntoone.both;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; public class HibernateTest {
private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before
public void init()
{
System.out.println("init"); // 1. 创建一个SessionFactory对象
sessionFactory = null;
Configuration configuration = new Configuration().configure(); // before 4.0
// sessionFactory = configuration.buildSessionFactory(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
// 2. 创建一个Session 对象
session = sessionFactory.openSession(); // 3. 开启事务
transaction = session.beginTransaction(); } @After
public void destory()
{
System.out.println("destory");
// 5. 提交事务
transaction.commit(); // 6. 关闭Session
session.close(); // 7. 关闭SesssionFactory
sessionFactory.close();
} @Test
public void testMany2OneSave()
{
Customer customer = new Customer();
customer.setCustomerName("BB"); Order order1 = new Order();
order1.setOrderName("order-5"); Order order2 = new Order();
order2.setOrderName("order-6"); // 设定关联关系
order1.setCustomer(customer);
order2.setCustomer(customer); customer.getOrders().add(order1);
customer.getOrders().add(order2); // 因为1的一端也要维护关联关系,所以会多出UPDATE
// 可以在1的一端的set节点指定inverse=true,来使1的一端放弃
// 关联关系,建议设定set的inverse=true,且先插入1的一端,后
// 插入多的一端,好处是不会多出update语句
session.save(customer);
session.save(order1);
session.save(order2); //
// session.save(order1);
// session.save(order2);
// session.save(customer);
} @Test
public void testOne2ManyGet()
{
// 1. 对n的一端的集合使用延迟加载
Customer customer = (Customer)session.get(Customer.class, 1);
System.out.println(customer.getCustomerName()); // session.close();
//3.可能会抛出LazyInitializationException异常 // 2. 返回的多的一端的集合时Hibernate内置的集合类型
// 该类型具有延迟加载和存放代理对象的功能
System.out.println(customer.getOrders().getClass()); //4. 在需要使用集合中元素的时候再进行初始化
// 下面就不会初始化,而只是发送一条count语句
System.out.println(customer.getOrders().size());
} @Test
public void testUpdate()
{
Customer customer = (Customer)session.get(Customer.class, 1);
customer.getOrders().iterator().next().setOrderName("BBB");
}
}

  再说说多对多

  N-N:

  Category类:

package nton;

import java.util.HashSet;
import java.util.Set; public class Category {
private Integer id;
private String name;
private Set<Item> items = new HashSet<Item>(); public Set<Item> getItems() {
return items;
}
public void setItems(Set<Item> items) {
this.items = items;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

  Item类:

package nton;

import java.util.HashSet;
import java.util.Set; public class Item {
private Integer id;
private String name;
private Set<Category> categories = new HashSet<Category>();
public Set<Category> getCategories() {
return categories;
}
public void setCategories(Set<Category> categories) {
this.categories = categories;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

  Category.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 10:55:34 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="nton">
<class name="Category" table="CATEGORY">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id> <property name="name" type="java.lang.String">
<column name="NAME" />
</property> <!-- table:指定中间表 -->
<set name="items" table="CATEGORY_ITEM">
<key>
<column name="C_ID" />
</key>
<!-- 使用many-to-many指定多对多的关联关系,column执行set集合
中的持久化类在中间表的外键列的名称
-->
<many-to-many class="Item" column="I_ID"/>
</set>
</class>
</hibernate-mapping>

  Item.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 10:55:34 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="nton">
<class name="Item" table="ITEM">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property> <set table="CATEGORY_ITEM" name="categories" inverse="true">
<key column="I_ID"></key>
<many-to-many class="Category" column="C_ID"></many-to-many>
</set>
</class>
</hibernate-mapping>

  这是双向多对多关联,双方各自用一个set存储关联的一方,需要通过一个中间表来确定关联的一方,中间表存储双方的键值,通过一方的键值,可以找到关联的另一方。关于单向多对一,可以看上面提供的链接。

  好了,关联关系就说的差不多了,不全面,有些没说,我只是按照我代码中的来说的,对于单向的一对一和单向的多对多,可以看下我上面给的链接。

  最后是代码:第一部分第二部分