首页 > 代码库 > Hibernate多对多操作

Hibernate多对多操作

---------------------siwuxie095

   

   

   

   

   

   

   

   

Hibernate 多对多操作

   

   

以用户和角色为例

   

   

   

(一)多对多映射配置

   

第一步:创建两个实体类,用户和角色

   

   

   

   

第二步:让两个实体类之间互相表示

   

(1)在用户实体类中表示多个角色

   

技术分享

   

   

(2)在角色实体类中表示多个用户

   

技术分享

   

   

   

   

第三步:配置映射关系

   

(1)配置基本的映射

   

(2)配置关联关系的映射(多对多关系

   

1)在用户的映射配置文件中,表示所有角色

   

技术分享

   

   

2)在角色的映射配置文件中,表示所有用户

   

技术分享

   

   

   

   

第四步:在核心配置文件中引入映射配置文件

   

技术分享

   

   

   

   

   

   

   

(二)多对多级联保存

   

如:添加两个用户,为每个用户添加两个角色

   

1)复杂写法

   

先在角色的映射配置文件中的 set 标签添加 inverse 属性,并

将其值设置为 true,再进行具体实现

   

技术分享

   

/**

* 多对多级联保存的复杂写法

*

*

* 手动加上 @Test 以进行单元测试(将自动导入 JUnit 4 jar 包)

*

* 选中方法名,右键->Run As->JUint Test

*/

@Test

public void testSave(){

 

SessionFactory sessionFactory=null;

Session session=null;

Transaction tx=null;

 

try {

//得到 SessionFactory 对象

sessionFactory=HibernateUtils.getSessionFactory();

//创建 Session 对象

session=sessionFactory.openSession();

//开启事务

tx=session.beginTransaction();

 

//添加两个用户,为每个用户添加两个角色

 

//(1)

//创建用户和角色对象

User user1=new User();

user1.setUserName("小白");

user1.setUserPassword("8888");

   

User user2=new User();

user2.setUserName("小黑");

user2.setUserPassword("4444");

 

Role role1=new Role();

role1.setRoleName("保镖");

role1.setRoleMemo("强大的保镖");

 

Role role2=new Role();

role2.setRoleName("秘书");

role2.setRoleMemo("漂亮的秘书");

 

Role role3=new Role();

role3.setRoleName("司机");

role3.setRoleMemo("称职的司机");

 

 

//(2)

//建立用户和角色对象的关系

//

//在用户实体类中表示角色,在角色实体类中表示用户

//

//具体:

//把角色对象放到用户对象的 Set 集合中

//把用户对象放到角色对象的 Set 集合中

//

//user1 --- role1 / role2

//user2 --- role1 / role3

//

//注意:如果建立了双向的关系,一定要有一方放弃外

//键维护权。如下

user1.getRoleSet().add(role1);

user1.getRoleSet().add(role2);

user2.getRoleSet().add(role1);

user2.getRoleSet().add(role3);

 

role1.getUserSet().add(user1);

role1.getUserSet().add(user2);

role2.getUserSet().add(user1);

role3.getUserSet().add(user2);

 

 

//(3)保存到数据库(级联保存)

session.save(user1);

session.save(user2);

session.save(role1);

session.save(role2);

session.save(role3);

 

/*

* 由于是多对多且进行了双向关联,所以一定要有一方

* 放弃外键维护权,否则将无法保存到数据库中

*

* 一般由被动方放弃外键维护权,这里角色是被动方

*

* 具体做法:

*

* 在角色的映射配置文件中的 set 标签中添加 inverse

* 属性,并将其值设置为 true

*/

 

 

//提交事务

tx.commit();

} catch (Exception e) {

//回滚事务

tx.rollback();

} finally {

//关闭资源

session.close();

sessionFactory.close();

}

}

   

   

   

2)简化写法

   

先在用户的映射配置文件中的 set 标签添加 cascade 属性,并

将其值设置为 save-update,再进行具体实现

   

技术分享

   

/**

* 多对多级联保存的简化写法

*

* 在用户的映射配置文件中的 set 标签

* 添加 cascade 属性,并将其值设置为

* save-update

*/

@Test

public void testSaveX(){

 

SessionFactory sessionFactory=null;

Session session=null;

Transaction tx=null;

 

try {

//得到 SessionFactory 对象

sessionFactory=HibernateUtils.getSessionFactory();

//创建 Session 对象

session=sessionFactory.openSession();

//开启事务

tx=session.beginTransaction();

 

//添加两个用户,为每个用户添加两个角色

 

//(1)

//创建用户和角色对象

User user1=new User();

user1.setUserName("小白");

user1.setUserPassword("8888");

   

User user2=new User();

user2.setUserName("小黑");

user2.setUserPassword("4444");

 

Role role1=new Role();

role1.setRoleName("保镖");

role1.setRoleMemo("强大的保镖");

 

Role role2=new Role();

role2.setRoleName("秘书");

role2.setRoleMemo("漂亮的秘书");

 

Role role3=new Role();

role3.setRoleName("司机");

role3.setRoleMemo("称职的司机");

 

 

//(2)

//建立用户和角色对象的关系

//

//在用户实体类中表示角色

//

//具体:

//把角色对象放到用户对象的 Set 集合中

//

//user1 --- role1 / role2

//user2 --- role1 / role3

user1.getRoleSet().add(role1);

user1.getRoleSet().add(role2);

user2.getRoleSet().add(role1);

user2.getRoleSet().add(role3);

 

 

//(3)保存到数据库(级联保存)

session.save(user1);

session.save(user2);

 

 

//提交事务

tx.commit();

} catch (Exception e) {

//回滚事务

tx.rollback();

} finally {

//关闭资源

session.close();

sessionFactory.close();

}

}

   

   

   

   

   

   

   

(三)多对多级联删除(一般不使用,仅作了解)

   

如:删除某个用户

   

先在用户的映射配置文件中的 set 标签添加 cascade 属性,并

将其值设置为 delete,再进行具体实现

   

技术分享

   

/**

* 多对多级联删除

*

* 简化写法:在用户的映射配置文件中的 set 标签

* 添加 cascade 属性,并将其值设置为 delete

*/

@Test

public void testDelete(){

 

SessionFactory sessionFactory=null;

Session session=null;

Transaction tx=null;

 

try {

//得到 SessionFactory 对象

sessionFactory=HibernateUtils.getSessionFactory();

//创建 Session 对象

session=sessionFactory.openSession();

//开启事务

tx=session.beginTransaction();

 

//(1)

//通过 id 查询用户对象

User user=session.get(User.class, 1);

 

//(2)

//调用 Session delete() 方法实现级联删除

session.delete(user);

 

//多对多级联删除,一般不使用,仅作了解即可

//

//注意:此时角色的映射配置文件中的 set 标签

//不能将 inverse 属性设为 true,否则将无法

//删除

//

//另外:set 标签也不能将 cascade 属性设为

//delete,否则 testSaveX() 方法保存的数据

//将全部删除

 

 

//提交事务

tx.commit();

} catch (Exception e) {

//回滚事务

tx.rollback();

} finally {

//关闭资源

session.close();

sessionFactory.close();

}

}

   

   

   

   

   

   

   

(四)维护第三张表

   

通过第三张表来维护多对多关系

   

如:让某个用户有某个角色

   

第一步:根据 id 查询用户和角色

   

第二步:把角色对象放到用户对象的 Set 集合中

   

技术分享

   

   

再如:让某个用户没有某个角色

   

第一步:根据 id 查询用户和角色

   

第二步:从用户对象的 Set 集合中移除角色对象

   

技术分享

   

   

/**

* 维护第三张表

*/

@Test

public void testTable(){

 

SessionFactory sessionFactory=null;

Session session=null;

Transaction tx=null;

 

try {

//得到 SessionFactory 对象

sessionFactory=HibernateUtils.getSessionFactory();

//创建 Session 对象

session=sessionFactory.openSession();

//开启事务

tx=session.beginTransaction();

 

//让某个用户有某个角色

 

//(1)根据 id 查询用户对象和角色对象

User user=session.get(User.class, 1);

Role role=session.get(Role.class, 3);

 

//(2)把角色对象放到用户对象的 Set 集合中

user.getRoleSet().add(role);

 

 

 

//让某个用户没有某个角色

 

//(1)根据 id 查询用户对象和角色对象

User userx=session.get(User.class, 1);

Role rolex=session.get(Role.class, 1);

 

//(2)从用户对象的 Set 集合中移除角色对象

userx.getRoleSet().remove(rolex);

 

 

//提交事务

tx.commit();

} catch (Exception e) {

//回滚事务

tx.rollback();

} finally {

//关闭资源

session.close();

sessionFactory.close();

}

}

   

   

   

   

   

   

   

工程结构目录如下:

   

技术分享

   

   

   

HibernateUtils.java:

   

package com.siwuxie095.utils;

   

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

   

public class HibernateUtils {

 

static Configuration cfg=null;

static SessionFactory sessionFactory=null;

 

//或: 加上 private final 亦可,不过此时不能等于 null

// private static final Configuration cfg;

// private static final SessionFactory sessionFactory;

 

//静态代码块

static {

//加载核心配置文件

cfg=new Configuration();

cfg.configure();

sessionFactory=cfg.buildSessionFactory();

 

}

 

//提供方法返回 sessionFactory

public static SessionFactory getSessionFactory() {

return sessionFactory;

}

 

 

//提供方法返回与本地线程绑定的 Session

public static Session getCurrentSession() {

return sessionFactory.getCurrentSession();

}

 

}

   

   

User.java:

   

package com.siwuxie095.entity;

   

import java.util.HashSet;

import java.util.Set;

   

//用户实体类

public class User {

 

private Integer uid; //用户 id

private String userName; //用户名称

private String userPassword; //用户密码

 

//在用户实体类中表示多个角色,即 一个用户可以有多个角色

//

//Hibernate 中要求使用 Set 集合表示"多"的数据

private Set<Role> roleSet=new HashSet<Role>();

 

 

public Set<Role> getRoleSet() {

return roleSet;

}

public void setRoleSet(Set<Role> roleSet) {

this.roleSet = roleSet;

}

 

public Integer getUid() {

return uid;

}

public void setUid(Integer uid) {

this.uid = uid;

}

 

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

 

public String getUserPassword() {

return userPassword;

}

public void setUserPassword(String userPassword) {

this.userPassword = userPassword;

}

 

}

   

   

   

Role.java:

   

package com.siwuxie095.entity;

   

import java.util.HashSet;

import java.util.Set;

   

//角色实体类

public class Role {

   

private Integer rid; //角色 id

private String roleName; //角色名称

private String roleMemo; //角色描述

 

//在角色实体类中表示多个用户,即 一个角色可以有多个用户

//

//Hibernate 中要求使用 Set 集合表示"多"的数据

private Set<User> userSet=new HashSet<User>();

   

 

public Set<User> getUserSet() {

return userSet;

}

public void setUserSet(Set<User> userSet) {

this.userSet = userSet;

}

 

public Integer getRid() {

return rid;

}

public void setRid(Integer rid) {

this.rid = rid;

}

 

public String getRoleName() {

return roleName;

}

public void setRoleName(String roleName) {

this.roleName = roleName;

}

 

public String getRoleMemo() {

return roleMemo;

}

public void setRoleMemo(String roleMemo) {

this.roleMemo = roleMemo;

}

 

}

   

   

   

HibernateManyToMany.java:

   

package com.siwuxie095.hibernatetest;

   

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.junit.Test;

   

import com.siwuxie095.entity.Role;

import com.siwuxie095.entity.User;

import com.siwuxie095.utils.HibernateUtils;

   

//多对多操作

public class HibernateManyToMany {

 

 

 

/**

* 多对多级联保存的复杂写法

*

*

* 手动加上 @Test 以进行单元测试(将自动导入 JUnit 4 jar 包)

*

* 选中方法名,右键->Run As->JUint Test

*/

@Test

public void testSave(){

 

SessionFactory sessionFactory=null;

Session session=null;

Transaction tx=null;

 

try {

//得到 SessionFactory 对象

sessionFactory=HibernateUtils.getSessionFactory();

//创建 Session 对象

session=sessionFactory.openSession();

//开启事务

tx=session.beginTransaction();

 

//添加两个用户,为每个用户添加两个角色

 

//(1)

//创建用户和角色对象

User user1=new User();

user1.setUserName("小白");

user1.setUserPassword("8888");

   

User user2=new User();

user2.setUserName("小黑");

user2.setUserPassword("4444");

 

Role role1=new Role();

role1.setRoleName("保镖");

role1.setRoleMemo("强大的保镖");

 

Role role2=new Role();

role2.setRoleName("秘书");

role2.setRoleMemo("漂亮的秘书");

 

Role role3=new Role();

role3.setRoleName("司机");

role3.setRoleMemo("称职的司机");

 

 

//(2)

//建立用户和角色对象的关系

//

//在用户实体类中表示角色,在角色实体类中表示用户

//

//具体:

//把角色对象放到用户对象的 Set 集合中

//把用户对象放到角色对象的 Set 集合中

//

//user1 --- role1 / role2

//user2 --- role1 / role3

//

//注意:如果建立了双向的关系,一定要有一方放弃外

//键维护权。如下

user1.getRoleSet().add(role1);

user1.getRoleSet().add(role2);

user2.getRoleSet().add(role1);

user2.getRoleSet().add(role3);

 

role1.getUserSet().add(user1);

role1.getUserSet().add(user2);

role2.getUserSet().add(user1);

role3.getUserSet().add(user2);

 

 

//(3)保存到数据库(级联保存)

session.save(user1);

session.save(user2);

session.save(role1);

session.save(role2);

session.save(role3);

 

/*

* 由于是多对多且进行了双向关联,所以一定要有一方

* 放弃外键维护权,否则将无法保存到数据库中

*

* 一般由被动方放弃外键维护权,这里角色是被动方

*

* 具体做法:

*

* 在角色的映射配置文件中的 set 标签中添加 inverse

* 属性,并将其值设置为 true

*/

 

 

//提交事务

tx.commit();

} catch (Exception e) {

//回滚事务

tx.rollback();

} finally {

//关闭资源

session.close();

sessionFactory.close();

}

}

   

/**

* 多对多级联保存的简化写法

*

* 在用户的映射配置文件中的 set 标签

* 添加 cascade 属性,并将其值设置为

* save-update

*/

@Test

public void testSaveX(){

 

SessionFactory sessionFactory=null;

Session session=null;

Transaction tx=null;

 

try {

//得到 SessionFactory 对象

sessionFactory=HibernateUtils.getSessionFactory();

//创建 Session 对象

session=sessionFactory.openSession();

//开启事务

tx=session.beginTransaction();

 

//添加两个用户,为每个用户添加两个角色

 

//(1)

//创建用户和角色对象

User user1=new User();

user1.setUserName("小白");

user1.setUserPassword("8888");

   

User user2=new User();

user2.setUserName("小黑");

user2.setUserPassword("4444");

 

Role role1=new Role();

role1.setRoleName("保镖");

role1.setRoleMemo("强大的保镖");

 

Role role2=new Role();

role2.setRoleName("秘书");

role2.setRoleMemo("漂亮的秘书");

 

Role role3=new Role();

role3.setRoleName("司机");

role3.setRoleMemo("称职的司机");

 

 

//(2)

//建立用户和角色对象的关系

//

//在用户实体类中表示角色

//

//具体:

//把角色对象放到用户对象的 Set 集合中

//

//user1 --- role1 / role2

//user2 --- role1 / role3

user1.getRoleSet().add(role1);

user1.getRoleSet().add(role2);

user2.getRoleSet().add(role1);

user2.getRoleSet().add(role3);

 

 

//(3)保存到数据库(级联保存)

session.save(user1);

session.save(user2);

 

 

//提交事务

tx.commit();

} catch (Exception e) {

//回滚事务

tx.rollback();

} finally {

//关闭资源

session.close();

sessionFactory.close();

}

}

 

 

/**

* 多对多级联删除

*

* 简化写法:在用户的映射配置文件中的 set 标签

* 添加 cascade 属性,并将其值设置为 delete

*/

@Test

public void testDelete(){

 

SessionFactory sessionFactory=null;

Session session=null;

Transaction tx=null;

 

try {

//得到 SessionFactory 对象

sessionFactory=HibernateUtils.getSessionFactory();

//创建 Session 对象

session=sessionFactory.openSession();

//开启事务

tx=session.beginTransaction();

 

//(1)

//通过 id 查询用户对象

User user=session.get(User.class, 1);

 

//(2)

//调用 Session delete() 方法实现级联删除

session.delete(user);

 

//多对多级联删除,一般不使用,仅作了解即可

//

//注意:此时角色的映射配置文件中的 set 标签

//不能将 inverse 属性设为 true,否则将无法

//删除

//

//另外:set 标签也不能将 cascade 属性设为

//delete,否则 testSaveX() 方法保存的数据

//将全部删除

 

 

//提交事务

tx.commit();

} catch (Exception e) {

//回滚事务

tx.rollback();

} finally {

//关闭资源

session.close();

sessionFactory.close();

}

}

 

 

/**

* 维护第三张表

*/

@Test

public void testTable(){

 

SessionFactory sessionFactory=null;

Session session=null;

Transaction tx=null;

 

try {

//得到 SessionFactory 对象

sessionFactory=HibernateUtils.getSessionFactory();

//创建 Session 对象

session=sessionFactory.openSession();

//开启事务

tx=session.beginTransaction();

 

//让某个用户有某个角色

 

//(1)根据 id 查询用户对象和角色对象

User user=session.get(User.class, 1);

Role role=session.get(Role.class, 3);

 

//(2)把角色对象放到用户对象的 Set 集合中

user.getRoleSet().add(role);

 

 

 

//让某个用户没有某个角色

 

//(1)根据 id 查询用户对象和角色对象

User userx=session.get(User.class, 1);

Role rolex=session.get(Role.class, 1);

 

//(2)从用户对象的 Set 集合中移除角色对象

userx.getRoleSet().remove(rolex);

 

 

//提交事务

tx.commit();

} catch (Exception e) {

//回滚事务

tx.rollback();

} finally {

//关闭资源

session.close();

sessionFactory.close();

}

}

}

   

   

   

User.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>

   

<!--

(1)

class 标签:配置实体类和数据库表的对应;

name 属性:实体类的全路径,即 全限定名;

table 属性:数据库表的名称(数据库表由 Hibernate 自动生成)

-->

<class name="com.siwuxie095.entity.User" table="t_user">

 

<!--

(2)

id 标签:配置实体类 id 和表 id 对应(主键);

name 属性:实体类里 id 属性名称;

column 属性:生成表中 id 字段名称

-->

<id name="uid" column="uid">

<generator class="native"></generator>

</id>

 

<!--

(3)

property 标签:配置其它属性和表中字段对应;

name 属性:实体类属性名称;

column 属性:生成表中字段名称

-->

<property name="userName" column="user_name"></property>

<property name="userPassword" column="user_password"></property>

 

<!--

(4)

set 标签:配置关联关系的映射(配置关联对象),代表一个 Set 集合;

name 属性:关联另一方的对象的 Set 集合的名称(在用户实体类中声明);

table 属性:第三张表的名称;

cascade 属性:save-update 表示级联保存,delete 表示级联删除(逗号隔开);

inverse 属性:true 表示放弃关系维护(放弃外键的维护权)(默认为 false

-->

 

<set name="roleSet" table="user_role" cascade="delete">

 

<!--

key 标签:配置当前对象(关联一方)在第三张表中的外键

column 属性:当前对象(关联一方)在第三张表中的外键名称

-->

<key column="user_id"></key>

 

<!--

many-to-many 标签:配置实体类的多对多关联;

class:关联另一方的类的全路径,即 角色实体类的全限定名;

column:关联的另一方在第三张表的外键名称,即 角色表在第三张表中的外键名称

-->

<many-to-many class="com.siwuxie095.entity.Role" column="role_id"></many-to-many>

</set>

</class>

</hibernate-mapping>

   

   

   

Role.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.siwuxie095.entity.Role" table="t_role">

 

<id name="rid" column="rid">

<generator class="native"></generator>

</id>

 

<property name="roleName" column="role_name"></property>

<property name="roleMemo" column="role_memo"></property>

 

<!--

set 标签:配置关联关系的映射(配置关联对象),代表一个 Set 集合;

name 属性:关联另一方的对象的 Set 集合的名称(在角色实体类中声明);

table 属性:第三张表的名称;

cascade 属性:save-update 表示级联保存,delete 表示级联删除(逗号隔开);

inverse 属性:true 表示放弃关系维护(放弃外键的维护权)(默认为 false

-->

<set name="userSet" table="user_role" cascade="save-update" inverse="false">

 

<!--

key 标签:配置当前对象(关联一方)在第三张表中的外键

column 属性:当前对象(关联一方)在第三张表中的外键名称

-->

<key column="role_id"></key>

 

<!--

many-to-many 标签:配置实体类的多对多关联;

class:关联另一方的类的全路径,即 用户实体类的全限定名;

column:关联的另一方在第三张表的外键名称,即 用户表在第三张表中的外键名称

-->

<many-to-many class="com.siwuxie095.entity.User" column="user_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://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

 

<!-- 第一部分:配置数据库信息(必须) -->

 

<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

<!-- 或使用 jdbc:mysql:///hibernate_db 代替,省略 localhost:3306 -->

<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_db</property>

<property name="hibernate.connection.username">root</property>

<property name="hibernate.connection.password">8888</property>

 

 

 

<!-- 第二部分:配置 Hibernate 信息(可选) -->

 

<!-- 输出底层 sql 语句 -->

<property name="hibernate.show_sql">true</property>

<!-- 输出底层 sql 语句格式 -->

<property name="hibernate.format_sql">true</property>

<!--

Hibernate 帮助创建表,不是自动创建,而需要配置之后。

update:如果已经有表,就更新,如果没有,就自动创建

-->

<property name="hibernate.hbm2ddl.auto">update</property>

<!--

配置数据库方言,让 Hibernate 框架识别不同数据库自己特有的语句

如:在 MySQL 中实现分页的关键字 limit,只能在 MySQL 中使用,而

Oracle 中实现分页的关键字则是 rownum

-->

<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

<!-- 配置 Session 绑定本地线程 -->

<property name="hibernate.current_session_context_class">thread</property>

 

 

 

<!-- 第三部分:引入映射配置文件,把映射配置文件放到核心配置文件(必须) -->

 

<mapping resource="com/siwuxie095/entity/User.hbm.xml"/>

<mapping resource="com/siwuxie095/entity/Role.hbm.xml"/>

 

</session-factory>

</hibernate-configuration>

   

   

   

   

   

   

   

   

   

   

   

【made by siwuxie095】

Hibernate多对多操作