1. 程式人生 > >hibernate框架學習筆記9:多對多關系案例

hibernate框架學習筆記9:多對多關系案例

ola 元數據 none _id Coding property turn 線程 rop

員工與角色案例:

一個員工可以是多種角色(總監,經理),一種角色可以是多個員工(保潔)

這裏發現無法使用外鍵表達關系,多對多總是創建第三張表來維護關系

這張表至少兩列,都是外鍵,分別引用兩張表的主鍵

員工(用戶)實體類:

技術分享圖片
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操作太過危險.尤其在多對多中.不建議使用.

這裏是一對多的文章,對比後更有收獲

http://www.cnblogs.com/xuyiqing/p/8453165.html

hibernate框架學習筆記9:多對多關系案例