`
tuhaitao
  • 浏览: 378808 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

JPA换进下慎用entity

    博客分类:
  • java
阅读更多
    今天跟一个同事调试代码,突然发现,诸如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例子jpajpa

    它提供了一种方式,让开发者可以用面向对象的编程模型来操作数据库,而无需直接编写SQL语句。JPA允许你在Java应用程序中以对象的形式处理数据,这些对象可以自动转换为数据库中的记录。 在JPA的例子中,我们通常会...

    jpa自动代码生成工具

    本工具可以根据数据库表自动生成JPA开发所需的实体JavaBean(带有jpa主注解)、repository及service类,提高开发效率;目前支持数据库:MYSQL;并提供配合演示使用的demo项目。

    JPA Demo 简单的了解下jpa

    1. **实体(Entity)**: 在JPA中,实体是映射到数据库表的Java类。它们通过`@Entity`注解标识,并且通常有一个`@Id`注解的属性作为主键。 2. **实体管理器(EntityManager)**: 这是JPA的核心组件,负责创建、查询...

    JPA Entity framework, inside of a Glassfish container

    在Glassfish中,JPA操作通常在容器管理的事务(CMT)下运行,这意味着服务器会自动处理事务的开始、提交和回滚。开发者只需编写业务逻辑,无需显式处理事务控制。 此外,JPA还提供了查询语言JPQL(Java Persistence...

    Spring Data JPA中文文档[1.4.3]_springdatajpa_erlang_waitxpf_

    2. **Entity Management**:Spring Data JPA 提供了对实体(Entity)的管理,包括实体的创建、更新、删除等操作。开发者可以通过 `EntityManager` 和 `EntityManagerFactory` 进行这些操作,但 Spring Data JPA 提供...

    JPA源文件/jpa学习

    JPA 2.0引入了许多增强功能,比如支持@OneToMany和@ManyToMany关系的双向映射,新增了@Temporal注解以处理日期和时间,增强了Criteria API,引入了@SecondaryTable注解以支持多表映射,还引入了Entity Graph来优化...

    JPA (一)

    1. **实体(Entity)** - 在 JPA 中,实体是数据库表的映射,对应于一个 Java 类。这些类通常会继承 `javax.persistence.Entity`,并且通过 `@Entity` 注解标记。实体类中的属性对应于数据库表的列。 2. **实体管理...

    JPA 标注 JPA标签手册

    例如,要将一个Java类标记为JPA实体,可以使用@Entity注解: ```java @Entity public class Employee implements Serializable { ... } ``` 您可以选择性地在实体类上添加注解以覆盖默认值,这被称为异常配置。 ...

    JPA教程,包括TOPLink JPA,Hibernate JPA,Open Jpa,jpa批注

    - `@Entity`:标记一个Java类作为JPA实体。 - `@Table`:指定实体对应的数据库表名。 - `@Id`:标记一个字段作为主键。 - `@GeneratedValue`:用于自动生成主键值,支持多种策略如IDENTITY、SEQUENCE、TABLE等。 - `...

    Gemini JPA 介绍资料

    Gemini JPA是在OSGi环境下(特别是Eclipse RCP)中使用的Java持久化框架。OSGi是一个模块化服务平台,允许在Java环境中动态地安装、启动、停止和卸载组件,而不会影响其他组件的正常运行。在Java开发中,持久化层...

    JPA中文解释,JPA的API

    标题中提到的"JPA中文解释"是指对于JPA的概念、原理、使用方法等进行了中文语言的详细解读,这对于中文环境下的开发者来说非常方便,能够更好地理解和应用JPA。JPA的核心理念是对象关系映射(ORM),它将Java对象...

    Pro JPA2 精通JPA2

    《Pro JPA2:精通Java™ Persistence API》是一本由Mike Keith和Merrick Schincariol撰写的关于Java持久化API(JPA)的权威指南。本书深入探讨了JPA2,即Java Persistence API的第二版,是Java EE 6标准的一部分。...

    JPA 开发指导文档

    1. **Entity Beans**:Entity Beans是JPA中的核心概念,它们代表数据库表的实体。开发者通过定义Entity类,并使用特定的注解(如@Entity、@Table等)来声明一个类为Entity Bean,然后将类的属性映射到数据库的列上。...

    jpa学习笔记 介绍了jpa中state的概念和应用

    在Java Persistence API (JPA) 中,理解和掌握实体(Entity)的状态对于有效地管理数据库中的对象至关重要。本篇学习笔记主要探讨了JPA中实体的状态及其转换,包括New、Managed、Detached和Removed四种状态。 首先...

    myabtis jpa插件源码

    2. **Entity类**:这些类通常用 JPA 注解进行标注,如 `@Entity` 表示该类为一个数据库表的映射,`@Table` 指定对应的表名,`@Id` 定义主键字段等。 3. **MyBatis配置**:检查 `mybatis-config.xml` 文件,了解如何...

    JPA+Netbeans6直接操作数据库

    JPA通过提供ORM(对象关系映射)机制,允许开发者用面向对象的方式来操作数据库,而无需直接编写SQL语句。 **NetBeans 6**是一款开源的集成开发环境(IDE),特别适合于Java开发。它提供了丰富的功能,包括代码编辑...

    jpa开发手册[文].pdf

    本文档涵盖了JPA的基础知识、JPA的体系架构、Entity Bean的定义和使用、EntityManager的配置和使用、JPA Query的使用等方面的内容。 1. 发展中的持久化技术 在Java应用程序中,持久化技术是一种非常重要的技术。 ...

    spring注解+spring data jpa文档+JPA文档.rar

    JPA通过`EntityManager`和`EntityTransaction`接口与数据库交互,`@Entity`注解标记实体类,`@Table`指定对应数据库表,`@Id`定义主键,`@GeneratedValue`用于自动生成主键值。JPA支持多种数据类型转换,以及复杂的...

    jpa

    JPA的核心组件包括实体(Entity)、实体管理器(EntityManager)、实体管理工厂(EntityManagerFactory)和查询语言(JPQL)。实体是JPA中的核心概念,它是Java类,代表数据库中的表或视图。实体管理器负责与数据库...

Global site tag (gtag.js) - Google Analytics