hibernate多表操作

一、表之间的关系

  1.一对一

  2.一对多

  3.多对多

二、表之间关系建表原则

  1.一对多:在多的一方创建一个外键,指向一的一方的主键

  

  2.多对多:创建一个中间表,中间表至少有两个字段,分别作为外键指向多对多双方的主键

  

3.一对一:主键一一对应,或当成一对多来看待。

三、一对多实现

  1)定义

1.在1的domain类中定义:

private Set<link> links= new HashSet<>();
在相应映射配置文件中:
<!--一对多-->
<set name="links"><!--set属性名称-->
    <key column="link_cust_id"></key><!--外键-->
    <one-to-many class="com.ual.domain.link"></one-to-many>
</set>

如果想要保存记录的时候保存其级联的记录,需要在set 后添加

cascade="save-update"

2.在多的domain类中定义:

    //一个联系人只对应一个客户
    private  customer customer;

在相应映射配置文件中:

<many-to-one name="customer" class="com.ual.domain.customer" column="link_cust_id" insert="false" update="false" lazy="false"></many-to-one>

加入lazy="false"后,在查询时会把记录相关的外键对应的记录一起查询出来。

3.在核心配置文件中,把映射关系写入

<mapping resource="com/ual/domain/customer.hbm.xml"/><!--告诉hibernate要操作哪些表,写入映射的配置文件的全路径-->
        <mapping resource="com/ual/domain/link.hbm.xml"></mapping>

4.实现插入

@Test
    public void test(){
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        customer c1 = new customer();
        c1.setCust_name("c1");
        customer c2= new customer();
        c2.setCust_name("c2");
        link link1 = new link();
        link1.setLink_name("link1");
        link link2 = new link();
        link2.setLink_name("link2");
        link link3 = new link();
        link3.setLink_name("link3");
        /*配置关系*/
        c1.getLinks().add(link1);
        c1.getLinks().add(link3);
        c2.getLinks().add(link2);
        link1.setCustomer(c1);
        link2.setCustomer(c2);
        link3.setCustomer(c1);
        /*保存联系人*/
        session.save(c1);
        session.save(c2);
        session.save(link1);
        session.save(link2);
        session.save(link3);

        transaction.commit();
    }

配置关系时,一般使用双向维护

2)查询

    @Test
    public void test2(){
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        link link=session.get(com.ual.domain.link.class,6L);
        transaction.commit();
        System.out.println(link.getLink_name());
        System.out.println(link.getCustomer().getCust_name());
    }

注:

级联操作:

  1.问题:在两张表建立一对多关系时,如果只保存一边的对象,会引发异常

  2.级联操作:

    什么时级联操作:在操作一个对象时,是否会操作其关联的对象

    级联分类:  

      级联保存或更新:cascade="save-update"

      级联删除:cascade="delete,save-update"

    级联是有方向性的:保存的是谁就到谁里面做级联,删除的是谁就到谁里面做级联

3)更新

  

   @Test
    public void test4(){
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //更新
        link link=session.get(link.class,10L);
        customer customer=session.get(com.ual.domain.customer.class,13L);
        //10本来关联12,现让其关联13
        //双向维护
        customer.getLinks().add(link);
        link.setCustomer(customer);
        session.update(customer);
        transaction.commit();
    }

注: 由于使用的双向维护,两方同时去维护一个外键,会产生性能问题,可以让一方放弃维护外键,只让外键所在的表维护外键

  需要配置:在1的配置文件中:加inverse="true"

四、多对多关系实现

1、表关系:用户角色表

2、多对多映射文件配置

role:

<?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">
<!--让java中的类与数据库中的表相关联,这样操作domain类就操作了与该类映射的表-->
<hibernate-mapping>
    <class name="com.ual.domain.role" table="role"><!--name对应类中,table对应表中-->
        <!--建立类属性,哪一个是主键,该主键需要跟数据库中的主键相对应-->
        <id name="r_id" column="r_id"><!--name对应类,column对应表-->
             <generator class="native"/><!--主键生成策略-->
        </id>
        <!--建立类中的普通属性和数据库中的字段进行关联-->
        <property name="r_name" column="r_name"/>
        <!--多对多-->
        <set name="users" table="role_user">
            <key column="r_id"></key>
            <many-to-many class="com.ual.domain.user" column="u_id"></many-to-many>
        </set>
    </class>

</hibernate-mapping>

user:

<?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">
<!--让java中的类与数据库中的表相关联,这样操作domain类就操作了与该类映射的表-->
<hibernate-mapping>
    <class name="com.ual.domain.user" table="user"><!--name对应类中,table对应表中-->
        <!--建立类属性,哪一个是主键,该主键需要跟数据库中的主键相对应-->
        <id name="u_id" column="u_id"><!--name对应类,column对应表-->
             <generator class="native"/><!--主键生成策略-->
        </id>
        <!--建立类中的普通属性和数据库中的字段进行关联-->
        <property name="u_name" column="u_name"/>
        <!--多对多
        name: 当前类下集合属性的名称
        table:多对多中间表的表名
        column:当前表的外键
        <many-to-many class="" column=""></many-to-many>
        class:当前类集合中对象的全路径
        column:集合中对象的外键
        -->
        <set name="roles" table="role_user">
            <key column="u_id"></key>
            <many-to-many class="com.ual.domain.role" column="r_id"></many-to-many>
        </set>
    </class>

</hibernate-mapping>

3、配置核心配置文件

<mapping resource="com/ual/domain/role.hbm.xml"></mapping>
        <mapping resource="com/ual/domain/user.hbm.xml"></mapping>

4、插入数据测试

 @Test
    public void test(){
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //创建用户
        user user1 = new user();
        user1.setU_name("user1");
        user user2 = new user();
        user2.setU_name("user2");
        //创建角色
        role role1 = new role();
        role1.setR_name("role1");
        role role2 = new role();
        role role3 = new role();
        role2.setR_name("role2");
        role3.setR_name("role3");

        //配置关系
        user1.getRoles().add(role1);
        user1.getRoles().add(role2);
        user2.getRoles().add(role1);
        user2.getRoles().add(role3);

        role1.getUsers().add(user1);
        role1.getUsers().add(user2);
        role2.getUsers().add(user1);
        role3.getUsers().add(user2);
        //保存
        session.save(user1);
        session.save(user2);
        
        transaction.commit();
    }

注意:在多对多建表时,使用双向维护,必须要使得一方放弃外键维护权,一般在被选择一方放弃外键维护,如角色被用户选择,让角色放弃外键维护权。否则,报外键重复异常。 

    

<set name="users" table="role_user" inverse="true" >
            <key column="r_id"></key>
            <many-to-many class="com.ual.domain.user" column="u_id" ></many-to-many>
        </set>

5、其他数据操作

   @Test
    public void test2(){
        //关系操作 就是操作内部集合
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //给用户1添加角色3
        user user = session.get(user.class, 1L);
        role role = session.get(role.class, 3L);
        user.getRoles().add(role);
        transaction.commit();
    }
  @Test
    public void test3(){
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        //更改,把用户2的角色3 修改为2
        user user2 = session.get(user.class, 2L);
        role role3 = session.get(role.class, 3L);
        role role2 = session.get(role.class, 2L);
         user2.getRoles().remove(role3);
         user2.getRoles().add(role2);
        transaction.commit();
    }

 

posted @ 2019-03-26 23:08  Uarealoser  阅读(433)  评论(0编辑  收藏  举报