Java持久层之Hibernate:04_多对多映射


多对多映射配置

  • 以用户和角色为例演示:
  • 第一步:创建实体类:用户和角色
  • 第二步:让两个实体类之间相互表示
    (1) 一个用户里面表示所有角色:使用set集合
    (2) 一个角色有多个用户:使用set集合
  • 第三步:配置映射关系
    (1) 基本配置
    (2) 配置多对多关系
  • 第四步:在核心配置文件中加载映射配置文件
  • 第五步:测试

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

  • 用户实体
public class User {
	private Integer id;
	private String name;
	private String password;
}
  • 角色实体
public class Role {
	private Integer id;	// 角色id
	private String name;// 角色名称
	private String memo; // 角色描述
}

第二步:让两个实体相互关联

  • 用户与角色关系的实体类
public class User {
	private Integer id;			// 用户id
	private String name;		// 用户名称
	private String password;	// 用户密码
	
	// 用户与角色之间的关系: 一个用户可以有多个角色: 一对多
	private Set<Role> roles = new HashSet<>();
}
  • 角色与用户关系的实体类
public class Role {
	private Integer id;	// 角色id
	private String name;// 角色名称
	private String memo; // 角色描述
	
	// 角色与用户之间的关系:一个角色里面可以有多个用户:一对多
	private Set<User> users = new HashSet<>();
}

第三步:配置映射关系

  • 用户的基本映射配置
<hibernate-mapping>
	<class name="com.ycom1024.hibernate.po.User" table="t_user">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		
		<property name="name" column="name"></property>
		<property name="password" column="password"></property>
	</class>
</hibernate-mapping>
  • 角色的基本映射配置
<hibernate-mapping>
   <class name="com.ycom1024.hibernate.po.Role" table="t_role">
   	<id name="id" column="id">
   		<generator class="native"></generator>
   	</id>
   	
   	<property name="name" column="name"></property>
   	<property name="memo" column="memo"></property>
   </class>
</hibernate-mapping>
  • 用户与角色关系的映射配置
<hibernate-mapping>
	<class name="com.ycom1024.hibernate.po.User" table="t_user">
		<!-- 用户的基本映射配置 -->
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		
		<property name="name" column="name"></property>
		<property name="password" column="password"></property>
		
		<!-- 用户与角色关系的映射配置: table是第三张表名称 -->
		<set name="roles" table="t_user_role">
			<!-- key里面配置的是外外键: 用户表在第三张表中的外键 -->
			<key column="userid"></key>
			
			<!-- 用户关联的角色的配置
				class属性: 角色实体类的全限定类名
				column属性:角色表在第三张表中的外键
			-->
			<many-to-many class="com.ycom1024.hibernate.po.Role" column="roleid"/>
		</set>
	</class>
</hibernate-mapping>
  • 角色与用户之间关系的映射配置
<hibernate-mapping>
	<class name="com.ycom1024.hibernate.po.Role" table="t_role">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		
		<property name="name" column="name"></property>
		<property name="memo" column="memo"></property>
		
		<set name="users" table="t_user_role">
			<key column="roleid"></key>
			
			<many-to-many class="com.ycom1024.hibernate.po.User" column="userid"/>
		</set>
	</class>
</hibernate-mapping>

第四步:在核心配置文件中加载映射配置文件

<?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>
		<!-- 访问数据库服务器的url -->
		<property name="hibernate.connection.url">jdbc:mysql:///hibernate07</property>
		<!-- 访问数据库服务器的用户名 -->
		<property name="hibernate.connection.username">root</property>
		<!-- 访问数据库服务器的密码 -->
		<property name="hibernate.connection.password">root</property>
		
		
		<!-- 第二部分:Hibernate自身的配置 -->
		<!-- 让Hibernate输出SQL语句 -->
		<property name="hibernate.show_sql">true</property>
		<!-- 让Hibenate输出的SQL语句是格式化的SQL语句 -->
		<property name="hibernate.format_sql">true</property>
		<!-- 让Hibernate帮助我们创建数据表 -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		<!-- 配置MySQL数据库方言 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<!-- 获取本地线程Session的配置 -->
		<property name="hibernate.current_session_context_class">thread</property>
		
		
		<!-- 第三部分:加载映射配置文件 -->
		<mapping resource="com/ycom1024/hibernate/po/Role.hbm.xml"/>
		<mapping resource="com/ycom1024/hibernate/po/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

第五步:测试

public class HibernateUtils {
	private static final SessionFactory sessionFactofy;
	
	static {
		Configuration cfg = new Configuration();
		cfg.configure();
		sessionFactofy = cfg.buildSessionFactory();
	}
	
	public static SessionFactory getSessionFactory() {
		return sessionFactofy;
	}
	
	public static void main(String[] args) {
		System.out.println("00000");
	}
}
  • 在指定的数据库中就生成了三张表
    在这里插入图片描述

多对多级联保存

  • 根据用户保存角色:
    (1) 第一步:在用户映射配置文件中的set标签进行配置cascade属性值为save-update
<hibernate-mapping>
	<class name="com.ycom1024.hibernate.po.User" table="t_user">
		<!-- 用户的基本映射配置 -->
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		
		<property name="name" column="name"></property>
		<property name="password" column="password"></property>
		
		<!-- 用户与角色关系的映射配置: table是第三张表名称 -->
		<set name="roles" table="t_user_role" cascade="save-update">
			<!-- key里面配置的是外外键: 用户表在第三张表中的外键 -->
			<key column="userid"></key>
			
			<!-- 用户关联的角色的配置
				class属性: 角色实体类的全限定类名
				column属性:角色表在第三张表中的外键
			-->
			<many-to-many class="com.ycom1024.hibernate.po.Role" column="roleid"/>
		</set>
	</class>
</hibernate-mapping>

(2) 第二步:写代码实现:创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了

@Test
public void testSave() {
	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	
	User user1 = new User();
	user1.setName("lucy");
	user1.setPassword("12345678");
	
	User user2 = new User();
	user2.setName("mary");
	user2.setPassword("12345689");
	
	// 总经理
	Role role1 = new Role();
	role1.setName("Mananger");
	role1.setMemo("Mananger");
	// 秘书
	Role role2 = new Role();
	role2.setName("mishu");
	role2.setMemo("mishu");
	// 保安
	Role role3 = new Role();
	role3.setName("baoan");
	role3.setMemo("baoan");
	
	// 用户1-->role1/role2
	user1.getRoles().add(role1);
	user1.getRoles().add(role2);
	// 用户2-->role2/role3
	user2.getRoles().add(role2);
	user2.getRoles().add(role3);
	// 保存用户
	session.save(user1);
	session.save(user2);
	
	tx.commit();
	session.close();
	sessionFactory.close();
}
----------------------------------------------------------------------------------
Hibernate: 
    insert 
    into
        t_user
        (name, password) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_role
        (name, memo) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_role
        (name, memo) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_user
        (name, password) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_role
        (name, memo) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_user_role
        (userid, roleid) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_user_role
        (userid, roleid) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_user_role
        (userid, roleid) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        t_user_role
        (userid, roleid) 
    values
        (?, ?)

在这里插入图片描述


多对多级联删除

  • 需求:在删除用户的时候,删除关联的角色
  • 第一步:根据id查询得到用户
  • 第二步:直接删除用户
@Test
public void testDelete1() {
	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	
	User user = session.get(User.class, 1);
	session.delete(user);
	
	tx.commit();
	session.close();
	sessionFactory.close();
}
----------------------------------------------------------------------------------
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.name as name2_1_0_,
        user0_.password as password3_1_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
Hibernate: 
    delete 
    from
        t_user_role 
    where
        userid=?
Hibernate: 
    delete 
    from
        t_user 
    where
        id=?

在这里插入图片描述

  • 楼上的代码并没有删除用户关联的角色信息:并没有删除角色表中的记录,只是删除了用户-角色关系表中的用户与角色的对应关系:那么如果要做到级联删除的话,需要在用户表的映射配置文件的set标签的中配置cascade属性值为delete
<hibernate-mapping>
	<class name="com.ycom1024.hibernate.po.User" table="t_user">
		<!-- 用户的基本映射配置 -->
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		
		<property name="name" column="name"></property>
		<property name="password" column="password"></property>
		
		<!-- 用户与角色关系的映射配置: table是第三张表名称 -->
		<set name="roles" table="t_user_role" cascade="save-update,delete">
			<!-- key里面配置的是外外键: 用户表在第三张表中的外键 -->
			<key column="userid"></key>
			
			<!-- 用户关联的角色的配置
				class属性: 角色实体类的全限定类名
				column属性:角色表在第三张表中的外键
			-->
			<many-to-many class="com.ycom1024.hibernate.po.Role" column="roleid"/>
		</set>
	</class>
</hibernate-mapping>
  • 测试代码
@Test
public void testDelete1() {
	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	
	User user = session.get(User.class, 5);
	session.delete(user);
	
	tx.commit();
	session.close();
	sessionFactory.close();
}
---------------------------------------------------------------------------
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.name as name2_1_0_,
        user0_.password as password3_1_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        roles0_.userid as userid2_2_0_,
        roles0_.roleid as roleid1_2_0_,
        role1_.id as id1_0_1_,
        role1_.name as name2_0_1_,
        role1_.memo as memo3_0_1_ 
    from
        t_user_role roles0_ 
    inner join
        t_role role1_ 
            on roles0_.roleid=role1_.id 
    where
        roles0_.userid=?
Hibernate: 
    delete 
    from
        t_user_role 
    where
        userid=?
Hibernate: 
    delete 
    from
        t_user_role 
    where
        roleid=?
Hibernate: 
    delete 
    from
        t_user_role 
    where
        roleid=?
Hibernate: 
    delete 
    from
        t_role 
    where
        id=?
Hibernate: 
    delete 
    from
        t_role 
    where
        id=?
Hibernate: 
    delete 
    from
        t_user 
    where
        id=?


维护第三张表关系

  • 需求:让某个用户有某个角色
    (1) 第一步:根据id查询用户和角色
    (2) 第二步: 把角色对象放到用户对象的集合中
    在这里插入图片描述
@Test
public void testUpdate1() {
	// 让用户lucy增加一个保安的角色
	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	
	User lucy = session.get(User.class, 7);  // 查询得到用户lucy
	Role baoan = session.get(Role.class, 12);// 查询得到角色保安
	// 将角色对象添加到用户对象的角色集合中即可
	lucy.getRoles().add(baoan);
	
	tx.commit();
	session.close();
	sessionFactory.close();
}
-----------------------------------------------------------------------------
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.name as name2_1_0_,
        user0_.password as password3_1_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        role0_.id as id1_0_0_,
        role0_.name as name2_0_0_,
        role0_.memo as memo3_0_0_ 
    from
        t_role role0_ 
    where
        role0_.id=?
Hibernate: 
    select
        roles0_.userid as userid2_2_0_,
        roles0_.roleid as roleid1_2_0_,
        role1_.id as id1_0_1_,
        role1_.name as name2_0_1_,
        role1_.memo as memo3_0_1_ 
    from
        t_user_role roles0_ 
    inner join
        t_role role1_ 
            on roles0_.roleid=role1_.id 
    where
        roles0_.userid=?
Hibernate: 
    insert 
    into
        t_user_role
        (userid, roleid) 
    values
        (?, ?)

在这里插入图片描述

  • 需求:让某个用户没有某个角色
    (1) 第一步:根据id查询用户和角色
    (2) 第二步:从用户对象的set集合对象中删除角色对象
@Test
public void testUpdate2() {
	// 让用户lucy去掉秘书的角色
	SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	
	User lucy = session.get(User.class, 7);  // 查询得到用户lucy
	Role mishu = session.get(Role.class, 11);// 查询得到角色秘书
	// 让用户对象中的set集合对象删除角色对象
	lucy.getRoles().remove(mishu);
	
	tx.commit();
	session.close();
	sessionFactory.close();
}
------------------------------------------------------------------------------
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.name as name2_1_0_,
        user0_.password as password3_1_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        role0_.id as id1_0_0_,
        role0_.name as name2_0_0_,
        role0_.memo as memo3_0_0_ 
    from
        t_role role0_ 
    where
        role0_.id=?
Hibernate: 
    select
        roles0_.userid as userid2_2_0_,
        roles0_.roleid as roleid1_2_0_,
        role1_.id as id1_0_1_,
        role1_.name as name2_0_1_,
        role1_.memo as memo3_0_1_ 
    from
        t_user_role roles0_ 
    inner join
        t_role role1_ 
            on roles0_.roleid=role1_.id 
    where
        roles0_.userid=?
Hibernate: 
    delete 
    from
        t_user_role 
    where
        userid=? 
        and roleid=?

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值