Hibernate:级联、检索的简单理解

1.cascade:实现级联cud

1.1.什么是cud

在Hibernate中,CUD是指对数据库进行增加(Create)、更新(Update)和删除(Delete)操作的简称。

  1. 创建(Create):通过Hibernate,可以使用持久化对象将数据插入到数据库中。将一个新的持久化对象保存到数据库时,Hibernate会自动生成相应的INSERT语句并执行,将数据插入到数据库表中。

  2. 更新(Update):在Hibernate中,可以通过修改持久化对象的属性值来更新数据库中的数据。当对已存在于数据库中的持久化对象进行更改时,Hibernate会自动检测对象的变化,并生成相应的UPDATE语句来更新数据库中的相关数据。

  3. 删除(Delete):使用Hibernate,可以从数据库中删除特定的数据行。当删除一个持久化对象时,Hibernate会生成相应的DELETE语句并执行,从数据库中删除对应的数据行。

这些CUD操作使得使用Hibernate进行数据库操作变得更加方便和简洁。开发人员可以通过使用Hibernate提供的API来执行这些操作,而无需手动编写复杂的SQL语句。同时,Hibernate还提供了事务管理和数据一致性等功能,使得数据库操作更加可靠和高效。

1.2 什么是级联(Cascade)

Cascade(级联)是一种配置选项,用于指定当对一个对象进行操作时,是否要同时对与之相关联的其他对象进行相同的操作。

Cascade可以应用于关联关系(Association)中的父子对象,例如一对多(OneToMany)、多对一(ManyToOne)、一对一(OneToOne)等。通过配置Cascade属性,可以实现对关联对象的级联操作。

常见的Cascade选项包括:

  1. CascadeType.ALL:表示对关联对象执行所有操作,包括创建、更新和删除。当对主对象进行操作时,会级联执行相同的操作到关联对象。

  2. CascadeType.PERSIST(或CascadeType.SAVE_UPDATE):表示对关联对象执行持久化操作(插入/保存和更新)。当对主对象进行持久化操作时,会级联执行相同的操作到关联对象。

  3. CascadeType.MERGE:表示对关联对象执行合并操作。当对主对象进行合并操作时,会级联执行相同的操作到关联对象。

  4. CascadeType.REMOVE:表示对关联对象执行删除操作。当对主对象进行删除操作时,会级联执行相同的操作到关联对象。

  5. CascadeType.REFRESH:表示对关联对象执行刷新操作。当对主对象进行刷新操作时,会级联执行相同的操作到关联对象。

通过使用Cascade属性,我们可以方便地管理关联对象之间的数据一致性,减少手动操作的复杂性。但需要注意,在使用Cascade选项时,需谨慎考虑潜在的数据完整性和性能方面的影响。

 1.3 代码测试

默认情况下,在一对多表之间的关系时,如:父亲和孩子;在关联从表时,不能直接关联

  •  创建数据库
CREATE TABLE `tab_father` (
  `fid` INT(11) NOT NULL AUTO_INCREMENT,
  `fname` VARCHAR(100) DEFAULT NULL,
  `fjob` VARCHAR(100) DEFAULT NULL,
  PRIMARY KEY (`fid`)
) ENGINE=INNODB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8



CREATE TABLE `tab_son` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `sname` varchar(100) DEFAULT NULL,
  `sage` int(11) DEFAULT NULL,
  `sfid` int(11) DEFAULT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_s_f` (`sfid`),
  CONSTRAINT `fk_s_f` FOREIGN KEY (`sfid`) REFERENCES `tab_father` (`fid`)
) ENGINE=InnoDB AUTO_INCREMENT=1003 DEFAULT CHARSET=utf8
  • mapper
<class name="test04.Father" table="tab_father">
    <!-- 指定主键列对应的属性 -->
    <id name="fid" column="fid" type="int">
        <generator class="identity"/>
    </id>
    <!--非主键对应的属性-->
    <property name="fname" column="fname" />
    <property name="fjob" column="fjob" />
    <!--给属性sonSet赋值-->
    <!--cascade="save-update" 实现级联保存-->
    <set name="sonSet" lazy="false">
        <key column="sfid"></key><!--key column="sfid"指定从表中的外键列名-->
        <one-to-many class="test04.Son"  />
    </set>
</class>
  •  启动类
//ctrl+p 提示参数列表
Father f1=new Father(20,"老王1","工程师");
Set<Son> sonSet=new HashSet<>();
//注意:关联的son不能设置id  否则不会插入son 直接修改son
sonSet.add(new Son(null,"王二小",19));
sonSet.add(new Son(null,"王之涣",29));
sonSet.add(new Son(null,"王石",39));
f1.setSonSet(sonSet);

System.out.println("添加::"+session.save(f1));
  •  打印的日志信息
Hibernate: insert into tab_father (fname, fjob) values (?, ?)
添加::16
Hibernate: update tab_son set sfid=? where sid=?
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: test04.Son
	at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:242)

 1.4 实现级联添加

默认情况:

//默认情况下  删除主表  把从表中关联的行的外键值更改为null
Father father;
father=new Father().setFid(15);//NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
father=(Father)session.get(Father.class,15);
session.delete(father);
  • 日志

Hibernate: select father0_.fid as fid1_0_, father0_.fname as fname1_0_, father0_.fjob as fjob1_0_ from tab_father father0_ where father0_.fid=?
Hibernate: select sonset0_.sfid as sfid1_, sonset0_.sid as sid1_, sonset0_.sid as sid2_0_, sonset0_.sname as sname2_0_, sonset0_.sage as sage2_0_, sonset0_.sfid as sfid2_0_ from tab_son sonset0_ where sonset0_.sfid=?
Hibernate: update tab_son set sfid=null where sfid=?
Hibernate: delete from tab_father where fid=?

 1.5  设置级联删除

  • mapper
 <!--cascade="delete" 实现级联删除-->
<set name="sonSet" cascade="delete" lazy="false">
            <key column="sfid"></key><!--key column="sfid"指定从表中的外键列名-->
            <one-to-many class="com.zhiyou100.test04.Son"  />
</set>
  • 测试代码 
  • Father father;
    father=new Father().setFid(11);//使用此方式删除 是把从表中关联的行的外键值更改为null
    //father=(Father)session.get(Father.class,9);//此方式会加从表关联的外键也进行删除
    session.delete(father);
  • 日志
Hibernate: select father0_.fid as fid1_0_, father0_.fname as fname1_0_, father0_.fjob as fjob1_0_ from tab_father father0_ where father0_.fid=?
Hibernate: select sonset0_.sfid as sfid1_, sonset0_.sid as sid1_, sonset0_.sid as sid2_0_, sonset0_.sname as sname2_0_, sonset0_.sage as sage2_0_, sonset0_.sfid as sfid2_0_ from tab_son sonset0_ where sonset0_.sfid=?
Hibernate: update tab_son set sfid=null where sfid=?
Hibernate: delete from tab_son where sid=?
Hibernate: delete from tab_son where sid=?
Hibernate: delete from tab_son where sid=?
Hibernate: delete from tab_father where fid=?
  • 注意:级联删除:根据需求/业务逻辑 选择设置

1.6 同时实现级联保存和删除

将属性改为cascade="all"
cascade="all"  等价于 cascade="delete" + cascade="save-update"

2.检索方式

  • 检索方式1:ognl:对象导航 Object Graph Navigation Language

  •  //          通过a对象获取其关联的b对象的信息
            Father f1=(Father)session.get(Father.class,1);
            for (Son s:f1.getSonSet()) {
                System.out.println(s);
                System.out.println("孩子:"+s);
            }
    
            Son s1=(Son)session.get(Son.class,111);
            f1=s1.getFather();
            System.out.println("父亲:"+f1);
  • 检索方式2:oid ::object id::通过对象的id获取对象

  • //检索方式2:oid ::object id::通过对象的id获取对象
            //通过session的两个方法:get/load
            f1=(Father)session.get(Father.class,1);
            f1=(Father)session.load(Father.class,2);
  • 检索方式3:hql: hibernate query language:::通过query接口访问数据库

  • //不是表名  是类名  不是列名  是属性名::::通过面向对象的思想操作数据库
            // 通过session的createQuery方法一个query接口
            //3.1 获取所有
            Query query=session.createQuery("from test04.Son");
            System.out.println("获取所有:::"+query.list());
            //3.2 获取一个
            query=session.createQuery("from test04.Son where sid=220");
            System.out.println("获取一个:::"+query.uniqueResult());
            //3.3 删除一个
            query=session.createQuery("delete from test04.Son where sid=220");
            System.out.println("删除一个:"+query.executeUpdate());
            //3.4 修改
            query=session.createQuery("update  test04.Son set sage=sage+1");
            System.out.println("修改多个:"+query.executeUpdate());
            //3.5 query不支持添加insert
  • 检索方式4:qbc:::query by Criteria::::通过session的createCriteria方法获取Criteria接口

  • //Criteria接口 是完全面向对象::::只能查询 不支持增删改
            Criteria criteria = session.createCriteria(Son.class);
            System.out.println("获取所有:::"+criteria.list());
            //4.2 获取一个
            Criterion c1= Restrictions.eq("sid",112);//获取sid=112的记录
            criteria.add(c1);//设置查询条件
            System.out.println("获取一个:"+criteria.uniqueResult());
            //4.3 复杂条件:sname like '%张%' or sage < 20
            criteria = session.createCriteria(Son.class);
            Criterion c21= Restrictions.like("sname","%张%");
            Criterion c22= Restrictions.lt("sage",20);
            Criterion c2=Restrictions.or(c21,c22);
            criteria.add(c2);//设置查询条件
            System.out.println("获取满足复杂条件的记录:"+criteria.list());
            //4.4 实现分页
            criteria = session.createCriteria(Son.class);
            criteria.setFirstResult(2);//设置起始索引::从0开始
            criteria.setMaxResults(3);//设置总记录数
            System.out.println("分页实现:"+criteria.list());
            // croteria支持方法链
            System.out.println("分页实现:"+session.createCriteria(Son.class).setMaxResults(3).setFirstResult(1).list());
  • 检索方式5:本地sql:::通过SqlQuery接口 由原始的sql语句 操作数据库

  • SQLQuery sqlQuery = session.createSQLQuery("select * from tab_son");
            System.out.println("获取所有:"+sqlQuery.addEntity(Son.class).list());
            sqlQuery = session.createSQLQuery("select * from tab_son where sid=211");
            System.out.println("获取一个:"+sqlQuery.addEntity(Son.class).uniqueResult());
            sqlQuery = session.createSQLQuery("insert into tab_son(sid,sname,sage) values(999,'呵呵呵',18)");
            System.out.println("添加一个:"+sqlQuery.addEntity(Son.class).executeUpdate());
            sqlQuery = session.createSQLQuery("update  tab_son set sage=sage+1");
            System.out.println("修改多个:"+sqlQuery.addEntity(Son.class).executeUpdate());
            sqlQuery = session.createSQLQuery("delete from tab_son where sid=113");
            System.out.println("删除多个:"+sqlQuery.addEntity(Son.class).executeUpdate());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值