hibernate学习(三)

突然感觉接触到了流币的知识,完全不懂。数据库方面的很多东西以前都没接触过。等今年开课在认真学一遍吧,暂时按照教程把我学到的东西整理下。

第一节 一对多映射列表(XML)

对于没有系统学习过数据库的我而言一开始并不明白这是什么意思。教程给的例子使用的联系人,感觉还是很好理解的。一个客户可以拥有多个用户,客户就是一联系人就是多,即一对多。

  • 创建用户实体类 Customer.java
package cn.lkangle.entity;

import java.util.HashSet;
import java.util.Set;

public class Customer {
    private Integer cid;
    private String name;
    private String attr;
    
    // 将联系人保存于set集合中
    private Set<LinkMan> linkMans = new HashSet<LinkMan>();
    ...
}
  • 创建联系人实体类 LinkMan.java
package cn.lkangle.entity;

public class LinkMan {
    private Integer lid;
    private String name;
    private String tel;

    // 用于保存所属客户
    private Customer customer;
    ...
}
  • XML映射配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
          "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
          
<hibernate-mapping>
     <!-- 一对多的客户映射配置 -->
    <class name="cn.lkangle.entity.Customer" table="t_customer">
        <id name="cid" column="cid">
            <generator class="native"></generator>
        </id>
        <property name="name" column="cname"></property>
        <property name="attr" column="cattr"></property>
        
        <set name="linkMans" cascade="save-update,delete">
            <key column="clid"></key>
            <one-to-many class="cn.lkangle.entity.LinkMan"></one-to-many>
        </set>
    </class>
    
    <!-- 一对多的联系人映射配置 -->
    <class name="cn.lkangle.entity.LinkMan" table="t_linkman">
        <id name="lid" column="lid">
            <generator class="native"></generator>
        </id>
        <property name="name" column="lname"></property>
        <property name="tel" column="ltel"></property>
        
        <many-to-one name="customer" class="cn.lkangle.entity.Customer" column="clid" cascade="save-update"></many-to-one>
    </class>
</hibernate-mapping>

客户的set标签与联系人的many-to-one标签是配置一对多的关键,其中的cascade属性设置级联操作。
级联具有方向性,在客户中添加只有在对客户进行操作时才会产生级联,在联系人中添加只有对联系人进行操作时才产生级联

cascade属性取值:

  • update-save 在更新和保存时进行级联
  • delete 在删除时进行级联
  • all 任何操作都进行级联
  • 一对多级联的CRUD操作
package cn.lkangle.threeday;

import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.lkangle.entity.Customer;
import cn.lkangle.entity.LinkMan;
import cn.lkangle.util.HbmUtil;

public class OnetoManyTest {
    /**
     * 双重级联效果 配置文件中客户和联系人都要设置级联属性 只是试试
     */
    @Test
    public void testSave2() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            System.out.println(session);
            tx = session.beginTransaction();
            
            Customer customer = new Customer();
            customer.setName("客户一");
            customer.setAttr("北京");
            
            LinkMan linkMan = new LinkMan();
            linkMan.setName("联系人一");
            linkMan.setTel("3333333333");
            LinkMan linkMan2= new LinkMan();
            linkMan2.setName("联系人二");
            linkMan2.setTel("865432222");
            
            customer.getLinkMans().add(linkMan);
            customer.getLinkMans().add(linkMan2);
            linkMan.setCustomer(customer);
            linkMan2.setCustomer(customer);
            
            session.save(linkMan);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
    /**
     * 级联查询操作
     */
    @Test
    public void testSelect() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            System.out.println(session);
            tx = session.beginTransaction();
            
//          Customer customer = session.get(Customer.class, 9);
//          System.out.println(customer);
//          Set<LinkMan> linkMans = customer.getLinkMans();
//          for (LinkMan linkMan : linkMans) {
//              System.err.println(linkMan);
//          }
            LinkMan linkMan = session.get(LinkMan.class, 2);
            System.out.println(linkMan);
            System.out.println(linkMan.getCustomer());

            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
    /**
     * 级联删除
     */
    @Test
    public void testDelete() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            System.out.println(session);
            tx = session.beginTransaction();
                        
//          LinkMan linkMan = session.get(LinkMan.class, 6);
//          session.delete(linkMan);

            Customer customer = session.get(Customer.class, 6);
            session.delete(customer);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
    /**
     * 级联修改 直接操作实体类就可以
     */
    @Test
    public void testUpdate() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            System.out.println(session);
            tx = session.beginTransaction();
            /**
             * 在这里如果设置了双向级联修改时会出现对外键进行两次修改,这是双向维护外键导致的,这样的效率就不高 
             * 推荐在客户中设置inverse="true"让其放弃对外键的维护,解决修改时会修改两次外键 
             */
            Customer customer = session.get(Customer.class, 9);
            
            LinkMan linkMan = session.get(LinkMan.class, 2);
            LinkMan linkMan2 = session.get(LinkMan.class, 7);
            // 因为放弃了客户对外键的维护 这里要更新联系人
            linkMan.setCustomer(customer);          
            linkMan2.setCustomer(customer);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
    /**
     * 级联保存
     */
    @Test
    public void testSave() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            System.out.println(session);
            tx = session.beginTransaction();
            
            Customer customer = new Customer();
            customer.setName("客户一");
            customer.setAttr("地址");
            
            LinkMan linkMan = new LinkMan();
            linkMan.setName("联系人一");
            linkMan.setTel("55555555");
            LinkMan linkMan2= new LinkMan();
            linkMan2.setName("联系人二");
            linkMan2.setTel("9999999999");
            
            customer.getLinkMans().add(linkMan);
            customer.getLinkMans().add(linkMan2);
            
            session.save(customer); // 客户要设置级联属性为save-update才能成功保存
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
}

XMl配置中set标签的inverse属性值
   inverse="false" 默认 不放弃级联
   inverse="true" 放弃级联
好处在进行update操作时可以提高效率减少一次数据库操作

第二节 多对多映射列表(XML)

多对多使用的人和角色的关系举例,即一个人可以同时有多个角色,一个角色同时可以是多个人的。

  • 创建人实体类 Man.java
package cn.lkangle.entity;

import java.util.HashSet;
import java.util.Set;

public class Man {
    private Integer man_id;
    private String man_name;
    private String man_attr;
    
    private Set<Role> roles = new HashSet<>();
    ...
}
  • 创建角色实体类 Role.java
package cn.lkangle.entity;

import java.util.HashSet;
import java.util.Set;

public class Role {
    private Integer role_id;
    private String role_name;
    
    private Set<Man> mans = new HashSet<>();
    ...
}
  • XML映射配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
          "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
          
<hibernate-mapping>
    <!-- 多对多用户映射配置 -->
    <class name="cn.lkangle.entity.Man" table="t_man">
        <id name="man_id" column="man_id">
            <generator class="native"></generator>
        </id>
        <property name="man_name" column="man_name"></property>
        <property name="man_attr" column="man_attr"></property>
        
        <set name="roles" table="mans_role" cascade="save-update,delete">
            <key column="man_id_3"></key>
            <many-to-many class="cn.lkangle.entity.Role" column="role_id_3"></many-to-many>
        </set>
    </class>
    
    <!-- 多对多角色映射配置 -->
    <class name="cn.lkangle.entity.Role" table="t_role">
        <id name="role_id" column="role_id">
            <generator class="native"></generator>
        </id>
        <property name="role_name"></property>
        
        <set name="mans" table="mans_role">
            <key column="role_id_3"></key>
            <many-to-many class="cn.lkangle.entity.Man" column="man_id_3"></many-to-many>
        </set>
    </class>
</hibernate-mapping>
 set集合属性 
         table: 第三个表的表名
         
         key属性
         column: 本表外键在第三张表中的字段名
         
         many-to-many属性
         class: 另一个实体类的路径
         column: 另一个表外键在第三张表中的字段名

两个实体类的配置对应关系如图:

  • 多对多的CRUD操作
package cn.lkangle.threeday;

import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.lkangle.entity.Man;
import cn.lkangle.entity.Role;
import cn.lkangle.util.HbmUtil;

public class ManyToMany {
    /**
     * 查询
     */
    @Test
    public void testManySelect() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            Man man = session.get(Man.class, 2);
            System.out.println(man);
            
            Set<Role> roles = man.getRoles();
            for (Role role : roles) {
                System.out.println(role);
            }
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
    /**
     * 修改 通过维护第三张表实现
     */
    @Test
    public void testManyUpdate() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            Man man = session.get(Man.class, 2);
            
            Role role = session.get(Role.class, 3);
            man.getRoles().add(role);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
    /**
     * 直接性级联删除 不推荐
     */
    @Test
    public void testManyDelete0() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            Man man = session.get(Man.class, 1);
            
            session.delete(man);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
    /**
     * 删除 通过维护第三张表实现
     */
    @Test
    public void testManyDelete() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            Man man = session.get(Man.class, 1);
            Role role = session.get(Role.class, 1);
            
            man.getRoles().remove(role);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
    /**
     * 多对多级联保存
     */
    @Test
    public void testMany() {
        Session session = null;
        Transaction tx = null;
        try {
            session = HbmUtil.getSession();
            tx = session.beginTransaction();
            
            Man man = new Man();
            man.setMan_name("严老");
            man.setMan_attr("兔斯基");
            Man man2 = new Man();
            man2.setMan_name("叶老");
            man2.setMan_attr("土耳其");
            
            Role role = new Role();
            role.setRole_name("老板");
            Role role2 = new Role();
            role2.setRole_name("秘书");
            Role role3 = new Role();
            role3.setRole_name("保安");
            
            man.getRoles().add(role);
            man.getRoles().add(role2);
            man2.getRoles().add(role);
            man2.getRoles().add(role3);
            
            session.save(man);
            session.save(man2);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            session.close();
        }
    }
}

实话我还没写过用到相关操作的项目、、、数据库也没系统学习过对此感觉很是生疏,看过教程也就会这一些基础的知识,更细节深入的知识还需要以后继续学习~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,569评论 18 139
  • (一)Struts、Spring、Hibernate、Mybatis框技术 1.Struts2.0有几种标签库 【...
    独云阅读 3,212评论 0 62
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,542评论 18 399
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,714评论 6 342
  • C++基础 重载 哪些运算符可以被重载:::,.,->,*,?:不能被重载 重载操作符的标志(operator) ...
    I踏雪寻梅阅读 205评论 0 2