Hong's Blog
Be Agile. Be Smart. Be Visionary. Be Dedicated.
部分内容搬运自SO上的一个回答。
如果managed entity有改动,那么在transaction提交时,JPA会自动地(待确定)帮你向数据库提交改动(不用显式地调用em.flush())。 一般来说,调用em.persist()时,entity的改动不会立即写到数据库中,JPA会暂缓执行这些改动对应的SQL语句, 等到transaction提交时再去执行这些SQL语句。这样有利于提高性能,比如JPA可以把不同改动对应的SQL语句放在一次请求里发给数据库。
em.flush()
em.persist()
有时候,用户可能希望立即执行SQL(通常是想得到SQL执行的“副作用”)。比如,用户想立即向数据库里插入一条记录, 以得到一个数据库自动产生的键值(也就是自动生成主键)。em.flush()会立即执行之前缓存的SQL,然后清空缓存。因为em.flush()会涉及到数据库的操作,所以会对 性能产生一点影响。如果transaction提交失败了,flush()时写到数据库的操作也会回滚。
flush()
JPA可以指定entity主键的生成方式。比如,下面的代码指定了entity的主键通过数据库的某个sequence来生成,
@Id @GeneratedValue(generator = "XYZSeq") @SequenceGenerator(name = "XYZSeq", sequenceName = "XYZ_SEQ", allocationSize = 1) private Long id;
如果去google “jpa persist auto generated id”,会发现很多sources都讲id只会在em.flush()调用后才会有值。 但是,上面的代码在EclipseLink + HANA的环境下,调用em.persist()后(调用em.flush()前)就会给id赋值。 调用em.persist()后,在EclipseLink的log里会有如下一条记录,
“jpa persist auto generated id”
id
...--Connection(1849633626)--Thread(Thread[http-bio-8091-exec-8,5,main])--SELECT XYZ_SEQ.NEXTVAL FROM DUMMY
这意味着,EclipseLink在执行persist()时会调用数据库的sequence去生成主键。 JPA的API文档里并没有讲persist()对entity主键的影响。所以,不同的JPA provider对persist()可能会有不同的实现。 当然,生成主键的行为也可能受到GenerationType的影响;比如GenerationType设成GenerationType.IDENTITY时,JPA provider 可能在persist()时就生成主键了。
persist()
GenerationType
GenerationType.IDENTITY
还有一个使用flush()的场景是,用JPQL查询时只会把数据库里的内容查询出来,所以如果想把内存里的entity的改 动也一起query出来要先flush()一下,把entity的改动刷到数据库里后再查询。(待确定)
在我的环境下,新建一个entity的对象,然后调用persist(),这时是可以在JPQL中query出这个新建的entity对象的(不需要调用一次flush())。
"select e from SomeEntity e where e.someField = :val"
不知道,对于其它(复杂的)JPQL是不是也是如此(待确定)。
还有个clear()函数,它可以把entity从persistence context里脱离出来;entity的改动不会被写到数据库里。
clear()
如果你觉得这篇文章对你有用,可以微信扫一扫表示🙏 / If you find this post is useful to you, buy me 🍶 via Wechat
flush() in JPA
部分内容搬运自SO上的一个回答。
如果managed entity有改动,那么在transaction提交时,JPA会自动地
(待确定)帮你向数据库提交改动(不用显式地调用em.flush()
)。 一般来说,调用em.persist()
时,entity的改动不会立即写到数据库中,JPA会暂缓执行这些改动对应的SQL语句, 等到transaction提交时再去执行这些SQL语句。这样有利于提高性能,比如JPA可以把不同改动对应的SQL语句放在一次请求里发给数据库。有时候,用户可能希望立即执行SQL(通常是想得到SQL执行的“副作用”)。比如,用户想立即向数据库里插入一条记录, 以得到一个数据库自动产生的键值(也就是自动生成主键)。
em.flush()
会立即执行之前缓存的SQL,然后清空缓存。因为em.flush()
会涉及到数据库的操作,所以会对 性能产生一点影响。如果transaction提交失败了,flush()
时写到数据库的操作也会回滚。关于上面提到的“自动生成主键”
JPA可以指定entity主键的生成方式。比如,下面的代码指定了entity的主键通过数据库的某个sequence来生成,
如果去google
“jpa persist auto generated id”
,会发现很多sources都讲id
只会在em.flush()
调用后才会有值。 但是,上面的代码在EclipseLink + HANA的环境下,调用em.persist()
后(调用em.flush()
前)就会给id
赋值。 调用em.persist()
后,在EclipseLink的log里会有如下一条记录,这意味着,EclipseLink在执行
persist()
时会调用数据库的sequence去生成主键。 JPA的API文档里并没有讲persist()
对entity主键的影响。所以,不同的JPA provider对persist()
可能会有不同的实现。 当然,生成主键的行为也可能受到GenerationType
的影响;比如GenerationType
设成GenerationType.IDENTITY
时,JPA provider 可能在persist()
时就生成主键了。还有一个使用flush()
的场景是,用JPQL查询时只会把数据库里的内容查询出来,所以如果想把内存里的entity的改 动也一起query出来要先flush()
一下,把entity的改动刷到数据库里后再查询。(待确定)在我的环境下,新建一个entity的对象,然后调用
persist()
,这时是可以在JPQL中query出这个新建的entity对象的(不需要调用一次flush()
)。不知道,对于其它(复杂的)JPQL是不是也是如此(待确定)。
还有个
clear()
函数,它可以把entity从persistence context里脱离出来;entity的改动不会被写到数据库里。如果你觉得这篇文章对你有用,可以微信扫一扫表示🙏 / If you find this post is useful to you, buy me 🍶 via Wechat