今天跟一个同事调试代码,突然发现,诸如findUserById(Integer uid)这样的方法,尽然产生了一条update的sql语句,感觉很奇怪,并没有发现任何更新的地方,怎么会产生这条update语句呢???
这个方法大致是这样的:
public User findUserById(Integer uid) {
return entityManager.find(User.class, uid);
}
仔细检查代码,却发现,在User类中,有这样的做法:
public class User implements Serializable {
... ...
private Date lastLoginTime;
public void setLastLoginTime(Date date) {
this.lastLoginTime = new Date();
}
... ...
}
以往用惯Hibernate的朋友(像我就是这样),可能会觉得find出一个对象,然后你怎么区更改这个对象,不会同步到数据库中去,而在JTA环境中,不是这样的,在JTA环境中,默认的,一个数据库的操作方法,在方法开始前就会开启一个事务,而在方法结束后就会提交这个事务,这个过程对程序员来说是透明的,程序员自己感觉不到,不用编写任何代码就能完成的事情。
不懂这个道理的朋友,可能很多人跟我一样,在学习的初期,大家都说EJB复杂,不好用,都被一本叫做XXX without EJB的书教唆至直接学习Spring + Hibernate + Status去了,一提起Spring都会说有多么多么的好,其中就有一个叫做“声明式事务管理”的东东,当时我一直不知道到底为啥要叫做“声明式事务”,就简单的理解成,用那个事务拦截器配置 add*、save*、delete*啊,这样配置,然后写出诸如addUser、saveUser这样的方法,就可以了,直到我有一次直去写jdbc的时候,我才知道,不使spring事务管理去写那个编程式事务到底是怎么回事:
tx.start();
... ...
tx.commit();
于是第一次了解了到底声明式事务是咋回事,这一扯就扯远了,不过也很无奈,谁叫我们大学里之交了java的语法,然后人家公司一招聘就要ssh之类的,逼的大家都ssh去了,一向自强的我又不愿意去培训那个什么“北大青鸟”、“新东方”当时我上大学的时,记得是这两个培训机构闹的最火,学费好贵,不是1W就是2W,我当时有两个选择,一个是买太超酷的电脑,一个就是去那里培训,几经思考海是抵挡不住“迪兰恒景”显卡的诱惑,最终搞了台1.2W 的电脑,于是开始了一边打“孤岛惊魂”,一边学java的日子....扯太远了,还是回归正体.
在EJB环境下,有个叫做entityManager的东东,这个东西与hibernate的session不太一样,session里去出来的对象,你可以去任意的修改里边的属性,直到你自己调用update这样的方法,才会更新到数据库中,但是在EJB下,却不是那个样子。
EJB中的entityManager的持久华对象大致上有三种(还有多的,大家补充一下):
1.调用entityManager.persist(Object o).
2.调用entituManager.merge(Object o).
3.调用entityManager.find(Class clazz,Object o)
第一种:
原来在数据库中没有这条记录,调用后会同步到数据库,前提条件是事务提交,那么默认的EJB环境下,是会自动提交这个事务,如果说,你在执行:
user.setName("111111");
entityManager.persist(user);
user.setName("222222");
这样最终,同步到数据库中的是user.name=22222.
为什么会这样呢,这与我们原来用的hibernate有很大的不同, 虽然hibernate也有persist这样的方法,但是很少在ssh这样的环境下使用,一般都只是使用save方法,那么
persist与save到底有什么不同呢,我怕自己描述不清除,从网上抄来了一段话:
persist把一个瞬态的实例持久化,但是并"不保证"标识符被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时间
用我的话说就是把一个对象交给entityManager来管理,但entiyManager并不保证立刻写进数据库,直到调用flush方法的时候才会提交,那么默认的当一个事务结束的时候,是会自动调用flash方法,这样才算吧对象同步到数据库中了,所以上边那个程序最终写到数据库中的是22222.
但是save方法会立即写入数据库.
第二种:
这个可以拿来与hibernate中的update方法来比较, 所谓要执行update,那表明了,数据库中已经有该对象所对应的记录,只是现在做一个更新操作,把对象中的属性值同步到数据库中去,当你执行update操作时,会立刻的打印出sql语句,而merge方法则不会,道理跟上边的save一样,只是把这个需要更新的对象交给entityManager管理,并不意味着立刻执行同步到数据库的操作,直到调用flush方法,entityManager才会去同步的数据库,同样的,事务结束的时候也会自动的调用flush方法.
第三种:
执行查找操作,如果数据库中有这条数据,则会返回一个引用给上层调用,那么这个过程经历了:
数据库-->entityManager-->findUserById,三个过程,这里我们吧findUserById这个方法叫做上层,它可以由更上层的方法调用,在调用findUserById方法时,默认的EJB容器会开启事务(如果findUserById还有更上层的方法也会同样的加入到这个事务中来),
拿我在最上边写的那个User类来说:
1.首先entityManager会从数据库中查找到记录
2.然后调用User的默认构造函数去生成一个对象
3.接着把数据库中的记录的值赋给这个新生对象,调用了User类的setXXX方法来赋值
4.把组装好的对象返回给上层调用
但上边代码setLastLoginTime的做法,意图是直接在bean里产生一个最新的时间,那么,在底层调用的时候,刚好使用了最新的Date实例覆盖了原有的值,导致了返回给上层的User对象的属性值与数据库中的不一致,所以执行一次findUserById导致产生update的操作.
不知不觉的开发过程貌似已经习惯了吧entity当作pojo来处理...
一点经验,写下来希望可以帮助大家:)
分享到:
相关推荐
本工具可以根据数据库表自动生成JPA开发所需的实体JavaBean(带有jpa主注解)、repository及service类,提高开发效率;目前支持数据库:MYSQL;并提供配合演示使用的demo项目。
jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联映射jpa 关联...
JPA教程JPA教程JPA教程JPA教程JPA教程
JPA开发文档 1. 发展中的持久化技术 2 1.1 JDBC 2 1.2关系对象映射(Object Relational Mapping,ORM) 2 1.3 Java数据对象(Java Data Object,JDO) 2 1.4 Java Persistence API(JPA) 2 2. JPA体系架构 3 清单1...
jpa jpa规范 jpa源码 jpa jpa规范 jpa源码
jpajpajpajpajpajpajpajpajpajpajpajpajpa
包括TOPLink JPA,Hibernate JPA,Open Jpa,jpa批注
JPA注解 详解 1、@Entity(name="EntityName") 必须,name为可选,对应数据库中一的个表 2、@Table(name="",catalog="",schema="") 可选,通常和@Entity配合使用,只能标注在实体的class定义处,表示实体对应的数据库表...
JPA
JPA Entity framework, inside of a Glassfish container
这是JPA标签配置手册,从ORACLE官方得到的资料,里面对JPA所有的标签都进行详细的说明。 Index of Annotations • A o @AssociationOverride o @AssociationOverrides o @AttributeOverride o @AttributeOverrides ...
主要内容: JPA 体系架构 Entity Bean EntityManager JPA Query
JPA视频_PPT及源码 · 1. JPA视频_概述 · 2. JPA视频_HelloWorld · 3. JPA视频_基本注解 · 4. JPA视频_Transient注解 · 5. JPA视频_Temporal注解 · 6. JPA视频_Table主键生成策略 · 7. JPA视频_...
一个简单的jpademo,可以简单的学习一下,超入门级
Springboot集成JPA,开箱即用
没有spring-data-jpa-entity-graph的生活 仅通过注释支持EntityGraph。 因此,对于存储库方法,必须在编译之前最多选择一个EntityGraph。 这样可以避免您在考虑运行时上下文的情况下选择最佳的EntityGraph :broken_...
'SpringDataJPA从入门到精通'分为12章 内容包括整体认识JPA、JPA基础查询方法、定义查询方法、注解式查询方法、@Entity实例里面常用注解详解、JpaRepository扩展详解、JPA的MVC扩展REST支持、DataSource的配置、乐观...
JPA的开发手册 1. 发展中的持久化技术 1 1.1 JDBC 1 1.2关系对象映射(Object Relational Mapping,ORM) 2 1.3 Java数据对象(Java Data Object,JDO) 2 1.4 Java Persistence API(JPA) 2 2. JPA体系架构 3 清单...
Spring Data JPA 简化 JPA 开发
Spring Data JPA API。 Spring Data JPA 开发文档。 官网 Spring Data JPA API。