Hibernate级联操作Cascade学之---save-update

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!习进阶更高效! 阅读详情

所在cascade,就是说我在更新一方的时候,可以根据这一方对象之间的关联关系,去对被关联方进行持久化,比如说Team和Student之间的1对多关系,使用cascade,可以在team方维护其持有的student集合时,自动对其新增,修改,删除的student对象进行持久化,而没必要显示的进行session.save(student)操作

数据库脚本:

 

create table student(id varchar(32primary key,
                     team_id 
varchar(32),
                     name 
varchar(32),
                     cardid 
varchar(32),
                     age 
int);

create table team(id varchar(32primary key,
                  team_id 
varchar(32),
                  teamname 
varchar(32));

                         
insert into team values("1","1","team1");
insert into student values("1","1","stu1","20070101",22);
insert into student values("2","1","stu2","20070102",23);

 持久化JavaBean

 

package Cascade.saveUpdate;


public class Student {
  
private String id;
  
private String cardid;
  
private String name;
  
private int age;
  
private Team team;
public String getId() {
    
return id;
}

public void setId(String id) {
    
this.id = id;
}

public String getCardid() {
    
return cardid;
}

public void setCardid(String cardid) {
    
this.cardid = cardid;
}

public String getName() {
    
return name;
}

public void setName(String name) {
    
this.name = name;
}

public int getAge() {
    
return age;
}

public void setAge(int age) {
    
this.age = age;
}


public Team getTeam() {
    
return team;
}

public void setTeam(Team team) {
    
this.team = team;
}

}



package Cascade.saveUpdate;


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

public class Team {
   
private String id;
   
private Set students=new HashSet();
   
private String teamName;
public String getId() {
    
return id;
}

public void setId(String id) {
    
this.id = id;
}

public Set getStudents() {
    
return students;
}

public void setStudents(Set students) {
    
this.students = students;
}

public String getTeamName() {
    
return teamName;
}

public void setTeamName(String teamName) {
    
this.teamName = teamName;
}



}

 

Hibernate.cfg.xml

 

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
>

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

<session-factory>
    
<property name="connection.username">root</property>
    
<property name="connection.url">
        jdbc:mysql://localhost:3306/schoolproject?characterEncoding=gb2312
&amp;useUnicode=true
    
</property>
    
<property name="dialect">
        org.hibernate.dialect.MySQLDialect
    
</property>
    
<property name="myeclipse.connection.profile">mysql</property>
    
<property name="connection.password">1234</property>
    
<property name="connection.driver_class">
        com.mysql.jdbc.Driver
    
</property>
    
<property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    
</property>
    
<property name="hibernate.show_sql">true</property>
    
<property name="current_session_context_class">thread</property>
    
<property name="jdbc.batch_size">15</property>
    
<mapping resource="Cascade/saveUpdate/Student.hbm.xml" />
    
<mapping resource="Cascade/saveUpdate/Team.hbm.xml" />



</session-factory>

</hibernate-configuration>

 

Student.hbm.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"
>
<!-- 
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="Cascade.saveUpdate.Student" table="student">
  
<id name="id" unsaved-value="null">
    
<generator class="uuid.hex"></generator>
  
</id>
  
<property name="cardid" type="string"/>
  
<property name="name" type="string"/>
  
<property name="age" type="int"/>
  
<many-to-one name="team" 
               column
="team_id"
               class
="Cascade.saveUpdate.Team"
               lazy
="no-proxy">
  
</many-to-one>
</class>

</hibernate-mapping>

 

Team.hbm.xml  这里先配置成cascade="none"

<?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"
>
<!-- 
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="Cascade.saveUpdate.Team" table="team" lazy="true">
       
<id name="id" column="id">
         
<generator class="uuid.hex"></generator>
       
</id>
       
<property name="teamName" column="teamname"></property>
      
       
<set name="students" lazy="true" inverse="false" cascade="none">
         
<key column="team_id"></key>
         
<one-to-many class="Cascade.saveUpdate.Student"/>
       
</set>
      
</class>
</hibernate-mapping>

 

测试代码:

 

package Cascade.saveUpdate;


import java.io.File;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class Test {


    
public static void main(String[] args) {

        String filePath
=System.getProperty("user.dir")+File.separator+"src/Cascade/saveUpdate"+File.separator+"hibernate.cfg.xml";
        File file
=new File(filePath);
        System.out.println(filePath);
        SessionFactory sessionFactory
=new Configuration().configure(file).buildSessionFactory();
        Session session
=sessionFactory.openSession();
        Transaction t
=session.beginTransaction();
        Student newStu
=new Student();  //建立一个student对象,瞬态
        newStu.setCardid("12345");
        newStu.setAge(
22);
        newStu.setName(
"newStu");
        Team team
=(Team)session.get(Team.class"1");//获得team对象
        Student removeStu=(Student)session.get(Student.class,"1");//获得需要删除的stu对象
        team.getStudents().add(newStu);  //增加student到team持有的student集合
        team.getStudents().remove(removeStu); //删除student到team持有的student集合
        t.commit();
        
    }


}

 

运行代码,结果如下:

Hibernate: select team0_.id as id1_0_, team0_.teamname as teamname1_0_ from team team0_ where team0_.id=?

Hibernate: select student0_.id as id0_0_, student0_.cardid as cardid0_0_, student0_.name as name0_0_, student0_.age as age0_0_, student0_.team_id as team5_0_0_ from student student0_ where student0_.id=?
Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id0_0_, students0_.cardid as cardid0_0_, students0_.name as name0_0_, students0_.age as age0_0_, students0_.team_id as team5_0_0_ from student students0_ where students0_.team_id=?

Hibernate: update student set team_id=null where team_id=? and id=?
Hibernate: update student set team_id=? where id=?

Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Cascade.saveUpdate.Student
 at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
 at org.hibernate.type.EntityType.getIdentifier(EntityType.java:397)
 at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:78)
 at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:755)
 at org.hibernate.persister.collection.AbstractCollectionPersister.insertRows(AbstractCollectionPersister.java:1364)
 at org.hibernate.action.CollectionUpdateAction.execute(CollectionUpdateAction.java:56)
 at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
 at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
 at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
 at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
 at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
 at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
 at Cascade.saveUpdate.Test.main(Test.java:30)

可以看到红色的异常,提示没有对象引用,是因为我们没有显示的调用session.save(newStu)又没有设置team端的cascade

如果代码改成session.save(newStu);  team.getStudents().add(newStu)就不会有任何问题了

 

下面,我们看下如果运用cascade="save-update"修正上面的错误,首先修改Team.hbm.xml

注意:cascade="saveupdate"和inverse="false"必须同时设置,才能让team维护级联关系,如果inverse="true"(不让Team维护关系,哪cascad设置也不会有任何作用,虽然可以新插入一条学生的记录,但其team_id为null,无法实现引用关系),如下图数据库表

 

<?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"
>
<!-- 
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="Cascade.saveUpdate.Team" table="team" lazy="true">
       
<id name="id" column="id">
         
<generator class="uuid.hex"></generator>
       
</id>
       
<property name="teamName" column="teamname"></property>
      
       
<set name="students" lazy="true" inverse="false" cascade="save-update">
         
<key column="team_id"></key>
         
<one-to-many class="Cascade.saveUpdate.Student"/>
       
</set>
      
</class>
</hibernate-mapping>

 

重新运行代码:

Hibernate: select team0_.id as id1_0_, team0_.teamname as teamname1_0_ from team team0_ where team0_.id=?
Hibernate: select student0_.id as id0_0_, student0_.cardid as cardid0_0_, student0_.name as name0_0_, student0_.age as age0_0_, student0_.team_id as team5_0_0_ from student student0_ where student0_.id=?
Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id0_0_, students0_.cardid as cardid0_0_, students0_.name as name0_0_, students0_.age as age0_0_, students0_.team_id as team5_0_0_ from student students0_ where students0_.team_id=?


Hibernate: insert into student (cardid, name, age, team_id, id) values (?, ?, ?, ?, ?)
Hibernate: update student set team_id=null where team_id=? and id=?
Hibernate: update student set team_id=? where id=?

可以看到,红色的部分插入了新数据,并使用update更新其team_id字段,维护约束关系

不过,需要主意的是,使用cascade="save-update"删除集合中的数据时候,不能真正的从数据库中删除记录,只是简单的讲其关联约束字段(如team_id)设置为null,被删除的对象还是保留在session缓存中,还是可以通过
removStu.setName("111")改变对象并进行持久化,如果需要使用这种方式删除对象并持久化,可以设置
cascade="all-delete-orphan"

Hibernate---关系映射(cascade级联操作属性:save-update、delete、all、none)cascade和inverse区别 联系(Relationship) 现实世界中事物内部以及事物之间的联系在信息世界中反映为实体内部的联系和实体之间的联系 实体间联系可分为: 一对一联系(1:1); 一对多联系(1:n); 多对多联系(m:n)。 (1).一对多联系(1:n) 实体一对多关联:如下图 Hibernate单向一对多关联: Hibernate双向一对多关联: ... 阅读详情

相关推荐

cascade="save-update" 与 inverse="true"使用讲解(回钦波)

今天在hibernate-hbm.xml里面做了调试发现casecade 和 inverse 的用法所在:     1.   public class FlowForm { private int id; private String template; private Set fields;   public Set getFields() {  return fields;...

huiqinbo的专栏 273

lazy、fetch、cascade的理解

lazy是延时加载,比方说一个对象A中包含了另一个对象B的set集合,在hibernate的映射文件中就会配置set集合对应关系。如果配置了延时加载=true,就是延时加载,这时候在A对象被查询出来时,不会同时去查询B对象,你获取的Set集合应该是空的或者是到使用的时候才去查询(可以看一下后台的sql)。因为你配置的是延时,如果是=false,查询A对象时,A对象中Set集...

Smile的博客 583

cascade="save-update" 级连的作用

hibernate 多对一中     有两人个实体,一个是Group public class Group { private int id; private String group; public String getGroup() { return group; } public void setGroup(String group) { this

greatmind829的专栏 1万+

JAVAWEB开发之Hibernate详解(二)——Hibernate的持久化类状态与转换、以及一级缓存详解、关联关系的映射(一对多、多对多、级联)...

持久化对象的状态 Hibernate持久化对象存在三种状态: 瞬时态 transient:(临时态) 不存在持久化标识OID,尚未与Hibernate Session关联对象,被认为是瞬时状态,失去引用将被JVM回收。特点:无持久化标识OID,未与Session关联。 持久态 persistent:存在持久化标识OID,与当前Session有关联,并且相关联的Session没有关闭,并且事务未提交...

iteye_18817的博客 1492

hibernate级联----cascade

1.cascade=”none”,默认值,告诉Hibernate忽略关系。2.cascade=”save-update”告诉Hibernate在下面这些情况导航关联:当事务提交时,当对象传给save()或update()方法并保存新初始化的瞬时实例及把更改持久到分离实例时。3. cascade=”delete”告诉Hibernate当对象传给delete()时导航关联并删除持久实例。4.casca

soleghost的专栏 3609

HIbernate(十)级联操作cascade和inverse管理关系

一、Cascade级联   级联 (org.hibernate.annotations.Cascade) 可以让我们增删改查数据时,操作一端的数据,同时级联操作被关联的另一端数据,降低对有映射关系的数据的操作复杂度 cascade级联,让操作级联到子实体,常用属性如下: save-update:保存和更新多的一端的数据时,一的一端的数据,可以一起保存和更新 ; none:不级联,默认就是no...

Waylon的博客 5949

hibernate级联操作

save-update: 级联保存(load以后如果子对象发生了更新,也会级联更新). 但它不会级联删除delete: 级联删除, 但不具备级联保存和更新all-delete-orphan: 在解除父子关系时,自动删除不属于父对象的子对象, 也支持级联删除和级联保存更新.all: 级联删除, 级联更新,但解除父子关系时不会自动删除子对象. delete-orphan:删除所有和当前对象解除关联

8994

Hibernate级联操作 注解

Hibernate级联操作 注解。如果设在many一端的<many-to-one>标签里,就是在删除many一端的数据时,会试图删除one一端的数据,如果仍然有many外键引用one,就会报“存在子记录”的错误;如果在one的一端同时也设置了cascade=“delete”属性,就会发生很危险的情况

Full Stack 1万+

hibernate】org.hibernate.MappingException: Unsupported cascade style: save_update

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment). log4j:WARN Please initialize the log4j system properly. org.hibernate.MappingException: Unsupported cascade style:

天书夜读 4849

hibernate级联cascade和关系维持inverse

hibernate的关联关系,重点在理解级联cascade和inverse   1、cascade一般用在级联保存,级联更新,级联删除上      1.1cascade注解有两种,一种是基于hibernate注解 org.hibernate.annotations.Cascade org.hibernate.annotations.CascadeType 支持一下级联 ALL, P

9819

hibernate级联操作详解

级联操作  一.简单的介绍 cascade和inverse (Employee – Department) l  Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似的操作,常用的cascade:          none,all,save-update,delete, lock,refresh,evict,replicate,persist,          m

张晓丛的专栏 2万+

Hibernate级联操作cascade选项

cascade可选的值包括:    all对所有的操作进行级联;     none,对所有的操作都不进行级联;    save-update,执行更新操作级联;    delete,执行删除操作级联。    all-delete-orphan,包含all和delete-orphan的行为none:在保存、更新或删除对象时,忽略其他关联的对象。他是cascade属性的默认值。save-update:当通过Session的save()、update()以及saveOrUpdate()方法保存或更新当前对象时

飘飘悠悠 1117

hibernate mysql cascade_Hibernate级联cascade)与反转(inverse)详解

Hibernate 的关联关系中,可以使用单向关联关系,也可以使用双向关联关系,在双向关联关系中,Hibernate 会同时控制双方的关系,这样在程序操作时,很容易出现重复操作的问题。为了解决这一问题,Hibernate 提供了反转操作,同时,为了在操作多表时,主表(主控方)操作后的数据能与关联表的数据保持一致,Hibernate 还提供了级联操作。接下来将对这两种操作进行详细讲解。反转操作在...

weixin_42503415的博客 322

Hibernate级联操作-cascade属性

Hibernte中级联操作cascade属性选项: 1. none :默认值,在保存、更新或删除对象时,忽略其他关联的对象 。 2. save-update :当通过 Session 的 save() 、 update() 以及 saveOrUpdate() 方法保     存或更新当前对象时,级联保存所有关联的新建的临...

SpringsSpace 410

Hibernatecascade有哪些

Cascade属性的取 1、none:忽略其他关联的对象,默认值。 2、save-update:当session通过save(),update(),saveOrUpdate()方法来保存或更新对象时,级联保存所有关联的新建的临时对象,并且级联更新所有关联的游离对象。 3、persist:当session通过persist()方法来保存当前对象时,会级联保存所有关联的新建的临时对象

lelong2002huyao的专栏 749

java中的cascade,Hibernatecascade作用

只有“关系标记”才有cascade属性;一个操作级联cascade可能触发多个关联操作。前一个操作叫“主控操作”,后一个操作叫“关联操作”。cascade属性的可能值有all: 所有情况下均进行关联操作,即save-update和delete。none: 所有情况下均不进行关联操作。这是默认值。save-update: 在执行save/update/saveOrUpdate时进行关联操作。del...

weixin_33597080的博客 638

Hibernate----cascade(级联)配置

级联操作:一个PO对象A 关联 另一个PO对象B,当A进行操作时,是否对B进行相应的操作。 取值:all|none|save-update|delete|all-delete-orphan|delete-orphan save-update级联保存或更新,当保存A,同时保存关联对象B,不需要手动执行save(B) delete:级联删除,当删除A时,同时删除关...

nonpricklycactus的博客 684

Java进阶之hibernatecascade与inverse

我们都知道的是cascade强调的是操作关联对象,inverse强调的是外键的维护权。在我们设置了级联操作后,在保存的时候就会级联保存另外的级联对象,而设置了inverse之后,如果两个对象之间有双向维护关系,就会在设置的一方放弃外键维护权,那它们两个共同使用的时候会产生什么结果呢?      我们可以通过一个简单的案例测试一下,就能得到结果,案例中customer与linkman为一对多关

不知不觉已变淡 1886
上一篇: 超级实用且不花哨的js代码大全
下一篇: Hibernate级联操作Cascade学之---delete
daryl715
博客等级 码龄25年 573粉丝 755原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值