1. 程式人生 > >八、Hibernate對映之多對多處理

八、Hibernate對映之多對多處理

以使用者和角色為例,一個使用者可以有多個角色,一個角色也可以屬於多個使用者,這種關係剛好是多對多的關係.

建立javabean

User.java

public class User {
	private Long user_id;
	private String user_name;
	private String user_password;
	private String user_state;
	
	//多對多中關聯的另一方
	private Set<Role> roles = new HashSet<Role>();
	
	//get set...
}

Role.java

public class Role {
	private Long role_id;
	private String role_name;
	
	//多對多中關聯的另一方
	private Set<User> users = new HashSet<User>();

	//get set...
}

建立對映檔案

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> <class name="blog.csdn.net.mchenys.domain.User" table="t_user"> <id name="user_id" column="user_id"> <generator class="native"/> </id> <property name="user_name" column="user_name"/> <
property
name="user_password" column="user_password"/>
<property name="user_state" column="user_state"/> <!-- set標籤屬性 name:javabean中集合的屬性名 table:中間表的名字,這個必現2邊保持一致 key標籤屬性 column:中間表中對應該類的外來鍵名 many-to-many標籤屬性 class:另一方的類全路徑名 column:另一方的類在中間表的外來鍵名 --> <set name="roles" table="user_role"> <key column="uid"/> <many-to-many class="blog.csdn.net.mchenys.domain.Role" column="rid"/> </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="blog.csdn.net.mchenys.domain.Role" table="t_role">
    		
    		<id name="role_id" column="role_id">
    			<generator class="native"/>
    		</id>
    		
    		
    		<property name="role_name" column="role_name"/>
    		
    		<!-- 
    		set標籤屬性
    			name:javabean中集合的屬性名
    			table:中間表的名字,這個必現2保持一致
    			inverse:true表示放棄維護外來鍵,多對多關係中必須有一方放棄維護,否則會報錯
    		key標籤屬性
    			column:中間表中對應該類的外來鍵名	
    		many-to-many標籤屬性
    			class:另一方的類全路徑名
    			column:另一方的類在中間表的外來鍵名
    		 -->
    		<set name="users" table="user_role" inverse="true">
    			<key column="rid"/>
    			<many-to-many class="blog.csdn.net.mchenys.domain.User" column="uid"/>
    		</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>

	<!-- 記住:先配置SessionFactory標籤,一個數據庫對應一個SessionFactory標籤 -->
	<session-factory>

		<!-- 必須要配置的引數有5個,4大引數,資料庫的方言 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day03</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">1234</property>

		<!-- 資料庫的方言 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>


		<!-- 可選配置 -->
		<!-- 顯示SQL語句,在控制檯顯示 -->
		<property name="hibernate.show_sql">true</property>
		<!-- 格式化SQL語句 -->
		<property name="hibernate.format_sql">true</property>
		<!-- 生成資料庫的表結構 
			update:如果沒有表結構,建立表結構。如果存在,不會建立,可動態新增欄位(新增屬性和對映即可),不能刪除欄位
		-->
		<property name="hibernate.hbm2ddl.auto">update</property>

		<!-- 開啟繫結本地的session -->
		<property name="hibernate.current_session_context_class">thread</property>
		

		<!-- 對映配置檔案,需要引入對映的配置檔案 -->
		<mapping resource="blog/csdn/net/mchenys/domain/User.hbm.xml"/>
		<mapping resource="blog/csdn/net/mchenys/domain/Role.hbm.xml"/>
	</session-factory>

</hibernate-configuration>	

雙向關聯儲存

/**
	 * 測試雙向關聯儲存
	 */
	@Test
	public void test1(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立使用者
		User u1 = new User();
		u1.setUser_name("小張");
		User u2 = new User();
		u2.setUser_name("小李");
		
		// 建立角色
		Role r1 = new Role();
		r1.setRole_name("管理員");
	
		Role r2 = new Role();
		r1.setRole_name("老師");
		
		// 雙向關聯
		u1.getRoles().add(r1);
		u1.getRoles().add(r2);
		r1.getUsers().add(u1);
		r2.getUsers().add(u1);
		
		u2.getRoles().add(r1);
		r1.getUsers().add(u2);
		
		session.save(u1);
		session.save(u2);
		session.save(r1);
		session.save(r2);
		
		tr.commit();
	}

級聯儲存

/**
	 * 級聯儲存:儲存使用者級聯儲存角色
	 */
	@Test
	public void test2(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立使用者
		User u1 = new User();
		u1.setUser_name("張三");
		User u2 = new User();
		u2.setUser_name("趙四");
		
		// 建立角色
		Role r1 = new Role();
		r1.setRole_name("經理");
		Role r2 = new Role();
		r2.setRole_name("銷售");
		
		//單項關聯
		u1.getRoles().add(r1);
		u1.getRoles().add(r2);
		u2.getRoles().add(r1);
		
		// 級聯儲存資料
		session.save(u1);
		session.save(u2);
		
		tr.commit();
	}

記得要在User.hbm.xml配置檔案中新增cascade屬性到set標籤上,例如:
在這裡插入圖片描述

如何修改中間表的資料

要修改中間表的資料也很簡單,反應到java層面就是操作集合中的物件,只不過得先通過Hibernate先去查找出相關聯的資料才能操作,下面以張三使用者刪除經理角色為例

/**
	 * 操作中間表資料:讓張三去掉經理這角色
	 */
	@Test
	public void test3() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 查詢張三使用者
		User user = session.get(User.class, 3L);
		// 查詢經理角色
		Role role = session.get(Role.class, 4L);

		// 操作集合來解除關聯,不需要執行update操作,因為持久態的物件可以有自動更新的功能
		user.getRoles().remove(role);

		// 提交
		tr.commit();
	}