1. 程式人生 > >Hibernate框架之多表查詢

Hibernate框架之多表查詢

1、多表設計(總結)

(1)多表關係
        1)一對一:
            表的設計原則(分表原則):
                優化表的效能
                基於語意化分表     
            一對一的兩張表 之間的關係怎麼維護?
                主外來鍵
                相同主鍵值
       2)一對多:
            建表原則:
                在一的一方有主鍵   主表
                多的一方有與主表的主鍵相關聯外來鍵    從表
        3)多對多
            建表原則:
                兩種主表(業務表) 中間存在一張中間表 
                中間表內部維護兩個外來鍵
                中間表分為兩種:
                    僅僅維護關係的中間表
                    不僅存在維護關係的外來鍵 還有其他業務欄位 例如:訂單表     訂單項表     商品表
(2)多表設計
        1)根據業務設計表模型
        2)分析表的關係:    分方向  看一條(起始表)
        3)一對一設計:     

學生表            學籍表

        4)一對多設計:

客戶表        聯絡人表
百度          張三
jd            李四
google        王武
              趙六
              田七
              孫八

        5)多對多設計(許可權5張表):
            1、通過使用者名稱和密碼才能登陸
            2、系統有不同的職務
            3、不同的職務可以有不同的許可權


            
使用者表            職務表(角色表)            許可權表(選單表、功能表)    
            
張三                CEO                        查下自己薪資
李四                CTO                        檢視全部人薪資
王武                CFO                        請假
田七                COO                        批假
                    程式設計師                    檢視專案進度
                                              檢視專案金額
                                                    
                                                    
     使用者角色關係表            角色許可權關係表

2、Hibernate一對多的操作

實體類結構:

//客戶表:
private long cust_id;//客戶編號(主鍵)
private String cust_name;//客戶名稱(公司名稱)
private String cust_source;//客戶資訊來源
private String cust_industry;//客戶所屬行業
private String cust_level;//客戶級別
private String cust_phone;//固定電話
private String cust_mobile;//行動電話
private Set<Linkman> linkmanSet = new HashSet<Linkman>();//多的一方集合

//聯絡人表
private long lkm_id;//'聯絡人編號(主鍵)',
private String lkm_name;// '聯絡人姓名',
private String lkm_gender;//'聯絡人性別',
private String lkm_phone;//'聯絡人辦公電話',
private String lkm_mobile;//'聯絡人手機',
private String lkm_email;// '聯絡人郵箱',
private String lkm_qq;//'聯絡人qq',
private String lkm_position;// '聯絡人職位',
private String lkm_memo;//'聯絡人備註',
//lkm_cust_id` bigint(32) NOT NULL COMMENT '客戶id',
private Customer customer;//一的一方物件

配置對映關係:

<!--客戶表關係對映-->
<hibernate-mapping>
    <class name="com.itheima.domain.Customer" table="cst_customer">
        <id name="cust_id" column="cust_id">
            <generator class="native"></generator>
        </id>
        <property name="cust_name" column="cust_name"></property>
        <property name="cust_source" column="cust_source"></property>
        <property name="cust_industry" column="cust_industry"></property>
        <property name="cust_level" column="cust_level"></property>
        <property name="cust_phone" column="cust_phone"></property>
        <property name="cust_mobile" column="cust_mobile"></property>

        <!-- 
			配置一對多  一個Customer 對應多個 聯絡人
			private Set<Linkman> linkmans = new HashSet<>();
			
			Set標籤name屬性:Set集合的名稱     (當前實體使用哪個變數與對方維護關係)
			key標籤的column:外來鍵的名稱
			one-to-many標籤的class:對方的全限定名

            級聯儲存:在儲存一方時 於此同時儲存與該方有關係的其他物件
			    cascade="save-update"
		    級聯刪除:在刪除一方時 於此同時刪除與該方有關係的另一方
			    cascade="delete"
		    放棄外來鍵維護權
			    inverse="true"
			    inverse直譯:反轉(反轉外來鍵維護權)		該方放棄外來鍵維護權
            查詢:延遲載入  lazy="true/false"  
		        查詢一的一方 多的一方預設是延遲載入

            結論:
			在開發中 習慣在一的一方配置級聯操作(cascade)  在一的一方配置放棄外來鍵維護權
			
		 -->
        <set name="linkmanSet" cascade="save-update,delete" inverse="true">
            <key column="lkm_cust_id"></key>
            <one-to-many class="com.itheima.domain.Linkman"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

<!--聯絡人表關係對映-->
<hibernate-mapping>
    <class table="cst_linkman" name="com.itheima.domain.Linkman">
        <id name="lkm_id" column="lkm_id">
            <generator class="native"></generator>
        </id>
        <property name="lkm_name" column="lkm_name"></property>
        <property name="lkm_gender" column="lkm_gender"></property>
        <property name="lkm_phone" column="lkm_phone"></property>
        <property name="lkm_mobile" column="lkm_mobile"></property>
        <property name="lkm_email" column="lkm_email"></property>
        <property name="lkm_qq" column="lkm_qq"></property>
        <property name="lkm_position" column="lkm_position"></property>
        <property name="lkm_memo" column="lkm_memo"></property>

        <!-- 
			配置多對一
			private Customer customer;
			
				name:當前實體使用哪個變數與對方維護關係
				class:對方的全限定
				column:外來鍵名稱
			
		 -->
        <many-to-one name="customer" column="lkm_cust_id" class="com.itheima.domain.Customer"></many-to-one>
    </class>
</hibernate-mapping>

配置核心引數:

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>

        <mapping resource="com/itheima/domain/Customer.hbm.xml"/>
        <mapping resource="com/itheima/domain/Linkman.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

測試:

public class OneToManyTets {

    //物件導航查詢
    @Test
    public void test3(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        Customer customer = session.get(Customer.class, 5l);
        Set<Linkman> linkmanSet = customer.getLinkmanSet();
        for(Linkman linkman : linkmanSet){
            System.out.println(linkman.getLkm_id()+"   "+linkman.getLkm_name());
        }

        //測試導航物件
        Linkman linkman = session.get(Linkman.class, 1l);
        System.out.println("Customer:"+customer.getCust_name());
        System.out.println("Linkman:"+linkman.getLkm_name());

        transaction.commit();
        HibernateUtils.close(session);
    }

    //級聯刪除
    @Test
    public void test2(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        //Linkman linkman = session.get(Linkman.class, 6l);
        //session.delete(linkman);
        Customer customer = session.get(Customer.class, 9l);
        session.delete(customer);

        transaction.commit();
        HibernateUtils.close(session);
    }

    //一對多儲存、級聯儲存
    @Test
    public void test1(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        Customer customer = new Customer();
        Linkman linkman1 = new Linkman();
        Linkman linkman2 = new Linkman();
        customer.setCust_name("CF");
        linkman1.setLkm_name("蓋比");
        linkman2.setLkm_name("拉倫多");
        //維護關係
        customer.getLinkmanSet().add(linkman1);
        customer.getLinkmanSet().add(linkman2);
        linkman1.setCustomer(customer);
        linkman2.setCustomer(customer);
        //儲存
        session.save(customer);
        //session.save(linkman1);
        //session.save(linkman2);

        transaction.commit();
        HibernateUtils.close(session);
    }
}

3、Hibernate多對多的操作

實體類結構

//使用者實體類
    private long user_id;//'使用者id',
    private String user_code;// '使用者賬號',
    private String user_name;// '使用者名稱稱',
    private String user_password;// '使用者密碼',
    private String user_state;// '1:正常,0:暫停',
    private Set<Role> roles = new HashSet<Role>();//多對多集合

//角色實體類
    private long role_id;
    private String role_name;//'角色名稱',
    private String role_memo;// '備註',
    private Set<User> users = new HashSet<User>();//多對多集合

配置對映關係

<!--使用者關係配置-->
<hibernate-mapping>
    <class name="com.itheima.domain.User" table="sys_user">
        <id name="user_id" column="user_id">
            <generator class="native"></generator>
        </id>
        <property name="user_code" column="user_code"></property>
        <property name="user_name" column="user_name"></property>
        <property name="user_password" column="user_password"></property>
        <property name="user_state" column="user_state"></property>

		<!-- 配置多對多 
				name:set集合的名稱
				key的column:當前實體在中間表中的外來鍵名稱(別人引用我的外來鍵)
				many-to-many的class:對方的全限定名
				many-to-many的column:代表對方的外來鍵名稱(我引用別人的外來鍵)
				table:中間表名稱
		-->
        <set name="roles" table="sys_user_role" inverse="true">
            <key column="user_id"></key>
            <many-to-many class="com.itheima.domain.Role" column="role_id"></many-to-many>
        </set>
    </class>
</hibernate-mapping>


<!--角色關係配置-->
<hibernate-mapping>
    <class name="com.itheima.domain.Role" table="sys_role">
        <id name="role_id" column="role_id">
            <generator class="native"></generator>
        </id>
        <property name="role_name" column="role_name"></property>
        <property name="role_memo" column="role_memo"></property>

        <set name="users" table="sys_user_role">
            <key column="role_id"></key>
            <many-to-many class="com.itheima.domain.User" column="user_id"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

配置核心配置引數

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>

        <mapping resource="com/itheima/domain/Role.hbm.xml"/>
        <mapping resource="com/itheima/domain/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

測試

public class ManyToManyTest {
    @Test
    public void test02(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        //給使用者新增角色
        User user = session.get(User.class, 9l);
        Role role = session.get(Role.class,13l);
        role.getUsers().add(user);
        session.save(role);

        transaction.commit();
        HibernateUtils.close(session);
    }

    @Test
    public void test01(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        //新增使用者和角色
        User user01 = new User();
        User user02 = new User();
        Role role01 = new Role();
        Role role02 = new Role();
        user01.setUser_name("魔獸世界");
        user02.setUser_name("LOL");
        role01.setRole_name("摩登莫西");
        role02.setRole_name("路西多亞");
        user01.getRoles().add(role01);
        user02.getRoles().add(role02);
        role01.getUsers().add(user01);
        role02.getUsers().add(user02);
        session.save(role01);
        session.save(role02);
        session.save(user01);
        session.save(user02);

        transaction.commit();
        HibernateUtils.close(session);
    }
}