員工與角色案例: 一個員工可以是多種角色(總監,經理),一種角色可以是多個員工(保潔) 這裡發現無法使用外鍵表達關係,多對多總是創建第三張表來維護關係 這張表至少兩列,都是外鍵,分別引用兩張表的主鍵 員工(用戶)實體類: package domain; //用戶實體 import java.util ...
員工與角色案例:
一個員工可以是多種角色(總監,經理),一種角色可以是多個員工(保潔)
這裡發現無法使用外鍵表達關係,多對多總是創建第三張表來維護關係
這張表至少兩列,都是外鍵,分別引用兩張表的主鍵
員工(用戶)實體類:
package domain; //用戶實體 import java.util.HashSet; import java.util.Set; public class User { private Long user_id; private String user_code; private String user_name; private String user_password; private Character user_state; //表達多對多 private Set<Role> roles = new HashSet<Role>(); public Long getUser_id() { return user_id; } public void setUser_id(Long user_id) { this.user_id = user_id; } public String getUser_code() { return user_code; } public void setUser_code(String user_code) { this.user_code = user_code; } public String getUser_name() { return user_name; } public void setUser_name(String user_name) { this.user_name = user_name; } public String getUser_password() { return user_password; } public void setUser_password(String user_password) { this.user_password = user_password; } public Character getUser_state() { return user_state; } public void setUser_state(Character user_state) { this.user_state = user_state; } public Set<Role> getRoles() { return roles; } public void setRoles(Set<Role> roles) { this.roles = roles; } }View Code
角色實體類:
package domain; //角色實體 import java.util.HashSet; import java.util.Set; public class Role { private Long role_id; private String role_name; private String role_memo; //表達多對多 private Set<User> users = new HashSet<User>(); public Long getRole_id() { return role_id; } public void setRole_id(Long role_id) { this.role_id = role_id; } public String getRole_name() { return role_name; } public void setRole_name(String role_name) { this.role_name = role_name; } public String getRole_memo() { return role_memo; } public void setRole_memo(String role_memo) { this.role_memo = role_memo; } public Set<User> getUsers() { return users; } public void setUsers(Set<User> users) { this.users = users; } }View Code
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 package="domain" > <class name="User" table="sys_user" > <id name="user_id" > <generator class="native"></generator> </id> <property name="user_code" ></property> <property name="user_name" ></property> <property name="user_password" ></property> <property name="user_state" ></property> <!-- 多對多關係表達 --> <!-- name: 集合屬性名 table: 配置中間表名 key |-column:外鍵,別人引用"我"的外鍵列名 class: 我與哪個類是多對多關係 column:外鍵.我引用別人的外鍵列名 --> <set name="roles" table="sys_user_role"> <key column="user_id" ></key> <many-to-many class="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 package="domain" > <class name="Role" table="sys_role" > <id name="role_id" > <generator class="native"></generator> </id> <property name="role_name" ></property> <property name="role_memo" ></property> <set name="users" table="sys_user_role"> <key column="role_id" ></key> <many-to-many class="User" column="user_id" ></many-to-many> </set> </class> </hibernate-mapping>View Code
核心配置文件: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> <!-- 資料庫url --> <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property> <!-- 資料庫連接用戶名 --> <property name="hibernate.connection.username">root</property> <!-- 資料庫連接密碼 --> <property name="hibernate.connection.password">xuyiqing</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 將hibernate生成的sql語句列印到控制台 --> <property name="hibernate.show_sql">true</property> <!-- 將hibernate生成的sql語句格式化(語法縮進) --> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 引入orm元數據 路徑書寫: 填寫src下的路徑 --> <property name="hibernate.connection.isolation">4</property> <!-- 指定session與當前線程綁定 --> <property name="hibernate.current_session_context_class">thread</property> <mapping resource="domain/User.hbm.xml" /> <mapping resource="domain/Role.hbm.xml" /> </session-factory> </hibernate-configuration>View Code
自定義工具類:
package utils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtils { private static SessionFactory sf; static{ //1 創建,調用空參構造 Configuration conf = new Configuration().configure(); //2 根據配置信息,創建 SessionFactory對象 sf = conf.buildSessionFactory(); } //獲得session => 獲得全新session public static Session openSession(){ //3 獲得session Session session = sf.openSession(); return session; } //獲得session => 獲得與線程綁定的session public static Session getCurrentSession(){ //3 獲得session Session session = sf.getCurrentSession(); return session; } }View Code
這裡先寫一段測試代碼:
public void fun1(){ //1 獲得session Session session = HibernateUtils.openSession(); //2 開啟事務 Transaction tx = session.beginTransaction(); //------------------------------------------------- //3操作 //1> 創建兩個 User User u1 = new User(); u1.setUser_name("張三"); User u2 = new User(); u2.setUser_name("李四"); //2> 創建兩個 Role Role r1 = new Role(); r1.setRole_name("保潔"); Role r2 = new Role(); r2.setRole_name("保全"); //3> 用戶表達關係 u1.getRoles().add(r1); u1.getRoles().add(r2); u2.getRoles().add(r1); u2.getRoles().add(r2); //4> 角色表達關係 r1.getUsers().add(u1); r1.getUsers().add(u2); r2.getUsers().add(u1); r2.getUsers().add(u2); //5> 調用Save方法一次保存 session.save(u1); session.save(u2); session.save(r1); session.save(r2); //------------------------------------------------- //4提交事務 tx.commit(); //5關閉資源 session.close(); }
看似很標準,不過運行會報錯
原因:預設的inverse屬性是維護的,兩方關係都要維護,造成主鍵重覆
解決辦法:
1.改變代碼:
@Test //保存員工以及角色 public void fun1(){ //1 獲得session Session session = HibernateUtils.openSession(); //2 開啟事務 Transaction tx = session.beginTransaction(); //------------------------------------------------- //3操作 //1> 創建兩個 User 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); u2.getRoles().add(r2); session.save(u1); session.save(u2); session.save(r1); session.save(r2); //------------------------------------------------- //4提交事務 tx.commit(); //5關閉資源 session.close(); }
2.配置文件修改:
Role的配置文件:
<set name="users" table="sys_user_role" inverse="true"> <key column="role_id" ></key> <many-to-many class="User" column="user_id" ></many-to-many> </set>
這時候運行那一段代碼就不會出錯
結論: 將來在開發中,如果遇到多對多關係.一定要選擇一方放棄維護關係.
一般誰來放棄要看業務方向. 例如錄入員工時,需要為員工指定所屬角色.
那麼業務方向就是由員工維護角色. 角色不需要維護與員工關係.角色放棄維護
多對多同樣有cascade屬性:
cascade級聯操作:
save-update: 級聯保存更新
delete:級聯刪除
all:級聯保存更新+級聯刪除
結論: cascade簡化代碼書寫.該屬性使不使用無所謂. 建議要用只用save-update.
如果使用delete操作太過危險.尤其在多對多中.不建議使用.
多對多的其他操作:
@Test //為張三新增一個角色 public void fun3(){ //1 獲得session Session session = HibernateUtils.openSession(); //2 開啟事務 Transaction tx = session.beginTransaction(); //------------------------------------------------- //3操作 //1> 獲得張三用戶 User user = session.get(User.class, 3l); //2> 創建總經理角色 Role r = new Role(); r.setRole_name("總經理"); //3> 將角色添加到用戶中 user.getRoles().add(r); //4> 將角色轉換為持久化 session.save(r); //------------------------------------------------- //4提交事務 tx.commit(); //5關閉資源 session.close(); } @Test //為張三解除一個角色 public void fun4(){ //1 獲得session Session session = HibernateUtils.openSession(); //2 開啟事務 Transaction tx = session.beginTransaction(); //------------------------------------------------- //3操作 //1> 獲得郝強勇用戶 User user = session.get(User.class, 3l); //2> 獲得要操作的角色對象(保潔,保全) Role r1 = session.get(Role.class, 1l); Role r2 = session.get(Role.class, 2l); //3> 將角色從用戶的角色集合中移除 user.getRoles().remove(r1); user.getRoles().remove(r2); //------------------------------------------------- //4提交事務 tx.commit(); //5關閉資源 session.close(); }
這裡是一對多的文章,對比後更有收穫
http://www.cnblogs.com/xuyiqing/p/8453165.html