欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java之hibernate表间关系

程序员文章站 2022-07-12 21:20:48
...

一对多

Java之hibernate表间关系
Customer实体类

表示一对多关系的容器:
    // 容器必须初始化才能保存东西
    private Set<LinkMan> linkMans = new HashSet<>();

LinkMan实体类

    // 使用一的对象来表示表与表之间的关系
    private Customer customer;

Customer.hbm.xml

<hibernate-mapping package="com.lanou3g.bean">
    <class name="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_linkman" column="cust_linkman" ></property>
        <property name="cust_phone" column="cust_phone" ></property>
        <property name="cust_mobile" column="cust_mobile" ></property>
        <!-- 配置表关系的容器 -->
        <!-- 
            name:实体类中容器的属性名
            column:表中的外键名
            class:表示一对多中 多表的类(全类名)

            inverse 控制是否维护外键关系
            默认维护外键的关系 默认值false 
            结语 inverse 可以减少hibernate 无用操作 提高效率

            cascade 级联操作 减少点代码
            save-update
            delete
            all == save-update + delete
            如果要用级联操作 就用save-update
            请慎用delete
         -->
        <set name="linkMans" inverse="true">
            <key column="lkm_cust_id"></key>
            <one-to-many class="LinkMan"/>
        </set>
    </class>
</hibernate-mapping>

LinkMan.hbm.xml

<hibernate-mapping package="com.lanou3g.bean">
    <class name="LinkMan" table="cst_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>

        <!-- 配置表关系 -->
        <!-- 
            name:表示关系的对象的属性名
            column:表中的外键名
            class:多对一关系中 对应的实体类名(全类名)
            注意:外键的属性 不要重复配置
         -->
        <many-to-one name="customer" column="lkm_cust_id" class="Customer"></many-to-one>

    </class>
</hibernate-mapping>

测试添加一个客户 两个联系人

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

        // 创建客户
        Customer customer = new Customer();
        customer.setCust_name("lanou");
        // 创建联系人
        LinkMan linkMan1 = new LinkMan();
        linkMan1.setLkm_name("wl");
        LinkMan linkMan2 = new LinkMan();
        linkMan2.setLkm_name("lck");
        // 添加实体类中的关系
        // 把联系人添加到集合中
        customer.getLinkMans().add(linkMan1);
        customer.getLinkMans().add(linkMan2);
        // 给联系人设置客户
        linkMan1.setCustomer(customer);
        linkMan2.setCustomer(customer);
        // 保存到数据库
        session.save(customer);
        session.save(linkMan1);
        session.save(linkMan2);

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


对hibernate执行的sql语句的优化
    打印的插入语句 是linkman在维护自己的表
    并且在插入的时候 已经插入了外键(外键已经有了)
    打印的更新语句 是Customer来维护从而打印出来的
    这里对外键的维护 两个表都维护一遍 造成了多余的sql语句操作
    使用inverse控制是否维护外键关系

删除客户为1的id为2的联系人

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

        // 获取id为1的客户
        // 持久态 在事务提交的时候 如果该对象被修改了 那么修改的数据 会被同步到数据库中
        Customer customer = session.get(Customer.class, 1l);
        // 获取id为2的联系人
        LinkMan linkMan = session.get(LinkMan.class, 2l);
        // 处理实体类的关系
        customer.getLinkMans().remove(linkMan);
        linkMan.setCustomer(null);
        // 从数据库中删除
        session.delete(linkMan);

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

为客户id为1 添加联系人

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

        // 获取id为1的客户
        Customer customer = session.get(Customer.class, 1l);
        // 创建联系人
        LinkMan linkMan = new LinkMan();
        linkMan.setLkm_name("zs");
        // 处理实体类的关系
        customer.getLinkMans().add(linkMan);
        linkMan.setCustomer(customer);
        // 保存到数据库
        session.save(linkMan);


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

测试级联操作(可以让你减少几行代码的工作量)

save-update:
    public void fun4() {
        Session session = HibernateUtils.getSession();
        Transaction transaction = session.beginTransaction();

        Customer customer = new Customer();
        customer.setCust_name("JD");
        LinkMan linkMan = new LinkMan();
        linkMan.setLkm_name("lsy");
        customer.getLinkMans().add(linkMan);
        //linkMan.setCustomer(customer);
        session.save(customer);
        //session.save(linkMan);

        transaction.commit();
        session.close();
    }
delete:
    @Test
    public void fun5() {
        Session session = HibernateUtils.getSession();
        Transaction transaction = session.beginTransaction();

        Customer customer = session.get(Customer.class, 1l);
        session.delete(customer);

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

多对多

Java之hibernate表间关系
User实体类

    // 表示多对多关系
    private Set<Role> roles = new HashSet<>();

Role实体类

    // 表示多对多关系
    private Set<User> users = new HashSet<>();

User.hbm.xml

<hibernate-mapping package="com.lanou3g.bean">
    <class name="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:对应容器的名
            table:中间表的名字
            column:被引用的外键
            *****************
            class:与之对应的表的类名(全类名)
            column: 前面class中被引用的外键
         -->
        <set name="roles" table="sys_user_role" inverse="true">
            <key column="user_id"></key>
            <many-to-many class="Role" column="role_id"></many-to-many>
        </set>

    </class>
</hibernate-mapping>

Role.hbm.xml

<hibernate-mapping package="com.lanou3g.bean">
    <class name="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="User" column="user_id"></many-to-many>
        </set>

    </class>
</hibernate-mapping>

保存两个员工两个角色

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

        User user1 = new User();
        user1.setUser_name("sc");
        User user2 = new User();
        user2.setUser_name("kd");

        Role role1 = new Role();
        role1.setRole_name("保镖");
        Role role2 = new Role();
        role2.setRole_name("保姆");

        user1.getRoles().add(role1);
        user1.getRoles().add(role2);
        user2.getRoles().add(role1);
        user2.getRoles().add(role2);
        role1.getUsers().add(user1);
        role1.getUsers().add(user2);
        role2.getUsers().add(user1);
        role2.getUsers().add(user2);

        session.save(user1);        
        session.save(user2);        
        session.save(role1);        
        session.save(role2);        

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

每个表默认都会维护自己的外键关系
中间表使用的联合主键 如果两张表都维护外键关系
也就是说 都会对中间表进行操作 这时会发生重复插入相同的外键值
注意:所以多对多操作必须要有一张表放弃对外键关系的维护

为id为1的员工增加一个角色

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

        User user = session.get(User.class, 1l);

        Role role = new Role();
        role.setRole_name("保洁");
        // 注意双侧关系都要添加上
        user.getRoles().add(role);
        role.getUsers().add(user);

        session.save(role);

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

为id为1的员工解除一个角色

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

        User user = session.get(User.class, 1l);
        Role role = session.get(Role.class, 2l);
        user.getRoles().remove(role);
        role.getUsers().remove(user);

        session.save(user);
        session.save(role);

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