先上一张图,关于几种关系映射:
抄一段解释:
基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用。关联关系分为上述七种,但是由于相互之间有各种关系,可以简化,例如:多对一与一对多映射,只是侧重的角度不对而已。
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存储关联的一方,需要通过一个中间表来确定关联的一方,中间表存储双方的键值,通过一方的键值,可以找到关联的另一方。关于单向多对一,可以看上面提供的链接。
好了,关联关系就说的差不多了,不全面,有些没说,我只是按照我代码中的来说的,对于单向的一对一和单向的多对多,可以看下我上面给的链接。