下面是双向多对多
首先是Bean持久化类,Category与Item
Category类
public class Category {
private Integer id;
private String name;
private Set<Item> items = new HashSet<Item>();
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;
}
public Set<Item> getItems() {
return items;
}
public void setItems(Set<Item> items) {
this.items = items;
}
}
Item类
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;
}
}
然后是持久化类的XML配置文件
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" >
<hibernate-mapping package="entity5">
<class name="Category" table="category">
<!-- id:表中的主键,name:类中的属性名 -->
<id name="id" type="java.lang.Integer">
<!-- name:表中的序列名 -->
<column name="id"/>
<!-- 指定主键的生成方式,native:使用数据库本地的方式 -->
<generator class="native"/>
</id>
<!-- property一般字段 -->
<property name="name" type="java.lang.String">
<column name="name"/>
</property>
<!--
注:双向多对多,两个持久化类的XML配置文件中,
set节点的table名要一致,同时,列名要交叉相同
并且其中一个set节点一定要放弃维护关联关系!
inverse="true"
本次在另一个XML中配置了此属性
-->
<!-- table:指定中间表名称 -->
<set name="items" table="category_item">
<key>
<column name="c_id"></column>
</key>
<!--
使用 many-to-many 指定多对多的关联关系,
column:执行Set集合中持久化类在中间表的外键列的名称
-->
<many-to-many class="Item" column="i_id"></many-to-many>
</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" >
<hibernate-mapping package="entity5">
<class name="Item" table="items">
<!-- id:表中的主键,name:类中的属性名 -->
<id name="id" type="java.lang.Integer">
<!-- name:表中的序列名 -->
<column name="id"/>
<!-- 指定主键的生成方式,native:使用数据库本地的方式 -->
<generator class="native"/>
</id>
<!-- property一般字段 -->
<property name="name" type="java.lang.String">
<column name="name"/>
</property>
<!--
注:双向多对多,两个持久化类的XML配置文件中,
set节点的table名要一致,同时,列名要交叉相同
并且其中一个set节点一定要放弃维护关联关系!
inverse="true"
-->
<!-- table:指定中间表名称 -->
<set name="categories" table="category_item" inverse="true">
<key>
<column name="i_id"></column>
</key>
<!--
使用 many-to-many 指定多对多的关联关系,
column:执行Set集合中持久化类在中间表的外键列的名称
-->
<many-to-many class="Item" column="c_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
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>
<!-- 配置连接数据库的基本信息 -->
<property name="connection.username">root</property>
<property name="connection.password">1234</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
<!-- 配置Hibernate的基本信息 -->
<!-- Hibernate所使用的数据库方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 执行操作时是否在控制台打印SQL -->
<property name="show_sql">true</property>
<!-- 是否对SQL进行格式化 -->
<property name="format_sql">true</property>
<!-- 指定自动生成数据表的策略 -->
<property name="hbm2ddl.auto">update</property>
<!-- 指定 关联的关系/映射 文件,引入Bean的xml文件 -->
<!-- 注:不是打. 用/ -->
<!-- <mapping resource="entity1/Customer.hbm.xml"/>
<mapping resource="entity1/Order.hbm.xml"/> -->
<!-- <mapping resource="entity2/Customer.hbm.xml"/>
<mapping resource="entity2/Order.hbm.xml"/> -->
<!-- <mapping resource="entity3/Department.hbm.xml"/>
<mapping resource="entity3/Manager.hbm.xml"/> -->
<mapping resource="entity5/Category.hbm.xml"/>
<mapping resource="entity5/Item.hbm.xml"/>
</session-factory>
</hibernate-configuration>
HibernateTest测试类
public class HibernateTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init() {
// 1.创建一个SessionFactory 对象
sessionFactory = null;
// 1.创建Configuration对象:对应Hibernate的基本配置信息和对象关系映射信息
// configure();读取配置文件,无参默认读取hibernate.cfg.xml
Configuration configuration = new Configuration().configure();
/**
* new Configuration 的几个方法
*
* 读取的是hibernate.properties配置文件
* 1:Configuration configuration = new Configuration();
*
* 读取配置文件,无参默认读取hibernate.cfg.xml
* 2:Configuration configuration = new Configuration().configure();
*
* 读取配置文件,读取指定xml,传入一个File
* 3:Configuration configuration = new Configuration().configure(file);
*/
// 2.创建一个ServiceRegistry对象
// Hibernate 的任何配置和服务都需要在该对象中注册后才有效
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
// 3.创建一个SessionFactory
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
// 2.创建一个Session对象
session = sessionFactory.openSession();
// 3.开启事物
transaction = session.beginTransaction();
}
@After
public void distroy() {
// 5.提交事物
transaction.commit();
// 6.关闭Session对象
session.close();
// 7.关闭SessionFactory对象
sessionFactory.close();
}
//增
@Test
public void test1(){
Category category1 = new Category();
category1.setName("c1");
Category category2 = new Category();
category2.setName("c2");
Item item1 = new Item();
item1.setName("i1");
Item item2 = new Item();
item2.setName("i2");
//设定关联关系
category1.getItems().add(item1);
category1.getItems().add(item2);
category2.getItems().add(item1);
category2.getItems().add(item2);
item1.getCategories().add(category1);
item1.getCategories().add(category2);
item2.getCategories().add(category1);
item2.getCategories().add(category2);
//保存
session.save(category1);
session.save(category2);
session.save(item1);
session.save(item2);
}
//查
@Test
public void test2(){
//懒加载,Category的items集合是代理对象,延迟加载
Category category = (Category) session.get(Category.class,1);
System.out.println(category.getName());
//底层实现需要连接中间表进行查询
Set<Item> items = category.getItems();
System.out.println(items.size());
}
}
在单向多对多中,两个Bean持久化类中只需写一个Set集合,并且在持久化类XML文件中只需配置一个Set节点,同时去掉两个Set节点中 inverse=”true” 属性,因为默认为false,所以配置了set的持久化类会默认去维护关联关系