多对多关系映射:
多对多和之前的一对多和多对一的区别就是需要再维护一个表,去存储两表的id,然后将两边进行关联起来
我们就以Developer和Project多对多的关系就行说明
首先建立实体类Developer.java,并建立getter和setter方法,属性如下,
private int d_id;
private String d_name;
// 开发人员,参数的多个项目
private Set<Project> projects = new HashSet<Project>();
private int prj_id;
private String prj_name;
// 项目下的多个员工
private Set<Developer> developers = new HashSet<Developer>();
然后对应写出主配置文件hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- jdbc驱动类 -->
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<!-- jdbc的url -->
<property name="hibernate.connection.url">jdbc:oracle:thin:@127.0.0.1:1521:XE</property>
<!-- jdbc的用户名 -->
<property name="hibernate.connection.username">evan</property>
<!-- jdbc的密码 -->
<property name="hibernate.connection.password">123</property>
<!-- 打印映射信息 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<!-- 方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<!-- 配置c3p0连接池 -->
<!-- 最大连接数 -->
<property name="hibernate.c3p0.max_size">20</property>
<!-- 最小连接数 -->
<property name="hibernate.c3p0.min_size">1</property>
<!-- 获取连接超时时间,若超过这个时间会抛出异常,单位:毫秒 -->
<property name="hibernate.c3p0.timeout">5000</property>
<!-- 创建PreparedStatement对象的最大数量 -->
<property name="hibernate.c3p0.max_statements">100</property>
<!-- 每个指定时间检查连接池中的空闲连接,时间单位:秒 -->
<property name="hibernate.c3p0.idle_test_period">150</property>
<!-- 当连接池使用完毕,c3p0再和数据库建立n个连接放置到连接池中 -->
<property name="hibernate.c3p0.acquire_increment">2</property>
<!-- 每次都验证连接是否可用 -->
<property name="hibernate.c3p0.validate">true</property>
<!-- 将session与当前线程绑定 -->
<property name="current_session_context_class">thread</property>
<!-- 映射路径 -->
<!-- <mapping resource="cn/qblank/hibernate/entity/stu.hbm.xml"/> -->
<!-- <mapping resource="cn/qblank/hibernate/entity/employee.hbm.xml"/>
<mapping resource="cn/qblank/hibernate/entity/dept.hbm.xml"/> -->
</session-factory>
</hibernate-configuration>
然后再对应地写出实体类的映射文件
project.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="cn.qblank.hibernate.entity">
<class name="Project" table="t_project">
<id name="prj_id" type="integer">
<generator class="native"></generator>
</id>
<property name="prj_name" column="prj_name" type="string"></property>
<!--
多对多映射:
1. 映射的集合属性: “developers”
2. 集合属性,对应的中间表: “t_relation”
3. 外键字段: prjId
4. 外键字段,对应的中间表字段: did
5. 集合属性元素的类型
-->
<set name="developers" table="t_realation" cascade="all">
<key column="prjId"></key>
<many-to-many column="did" class="Developer"></many-to-many>
</set>
</class>
</hibernate-mapping>
developer.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="cn.qblank.hibernate.entity">
<class name="Developer" table="t_developer">
<id name="d_id" type="integer">
<generator class="native"></generator>
</id>
<property name="d_name" column="d_name" type="string"></property>
<!--
多对多映射配置: 员工方
name 指定映射的集合属性
table 集合属性对应的中间表
key 指定中间表的外键字段(引用当前表t_developer主键的外键字段)
many-to-many
column 指定外键字段对应的项目字段
class 集合元素的类型
-->
<set name="projects" table="t_realation">
<key column="did"></key>
<many-to-many column="prjId" class="Project"></many-to-many>
</set>
</class>
</hibernate-mapping>
接下来,我们就来测试一下
package cn.qblank.hibernate.test;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import cn.qblank.hibernate.entity.Developer;
import cn.qblank.hibernate.entity.Project;
public class ManyToMany {
private static SessionFactory factory;
private static Transaction trans = null;
static {
factory = new Configuration()
.configure()
.addClass(Project.class)
.addClass(Developer.class) // 测试时候使用
.buildSessionFactory();
}
public static void main(String[] args) {
save();
}
// 1. 多对多,保存 【只能通过一方维护另外一方,不能重复维护!】
public static void save() {
Session session = factory.openSession();
trans = session.beginTransaction();
/*
* 模拟数据:
京东商城(老王,evan)
租车系统(老丁,evan)
*/
// 创建项目对象
Project prj_jd = new Project();
Project prj_zc = new Project();
prj_jd.setPrj_name("京东商城");
prj_zc.setPrj_name("租车系统");
// 创建员工对象
Developer dev_evan = new Developer();
Developer dev_wang = new Developer();
Developer dev_ding = new Developer();
dev_evan.setD_name("evan");
dev_wang.setD_name("老王");
dev_ding.setD_name("老丁");
// 关系 【项目方】
//京东商城
prj_jd.getDevelopers().add(dev_evan);
prj_jd.getDevelopers().add(dev_wang);
//租车系统
prj_zc.getDevelopers().add(dev_evan);
prj_zc.getDevelopers().add(dev_ding);
try {
// 保存
//插入项目
session.save(prj_jd);
session.save(prj_zc); // 必须要设置级联保存
trans.commit();
} catch (HibernateException e) {
e.printStackTrace();
trans.rollback();
}finally{
session.close();
}
}
}
运行结果如下:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into t_project (prj_name, prj_id) values (?, ?)
Hibernate: insert into t_developer (d_name, d_id) values (?, ?)
Hibernate: insert into t_developer (d_name, d_id) values (?, ?)
Hibernate: insert into t_project (prj_name, prj_id) values (?, ?)
Hibernate: insert into t_developer (d_name, d_id) values (?, ?)
Hibernate: insert into t_realation (prjId, did) values (?, ?)
Hibernate: insert into t_realation (prjId, did) values (?, ?)
Hibernate: insert into t_realation (prjId, did) values (?, ?)
Hibernate: insert into t_realation (prjId, did) values (?, ?)
数据库的表的结果如下: