为什么没有读取JPA find()方法未提交的更改?

时间:2016-10-29 08:21:01

标签: java jpa eclipselink wildfly-10

我对JPA行为感到困惑,我没想到会这样做(使用Eclipselink)。

我在Wildfly 10(JDK-8)上运行无状态会话EJB(3.2)。我的方法调用是 - 默认情况下 - 封装在事务中。 现在,我的业务方法在读取和更新实体bean时,无法识别更新 - 尤其是实体的版本号。所以我的电话会产生一个

org.eclipse.persistence.exceptions.OptimisticLockException

我的代码看起来简化为:

public ItemCollection process(MyData workitem) {

    ....
    // load document from jpa
    persistedDocument = manager.find(Document.class, id);
    logger.info("@version=" + persistedDocument.getVersion()); 
    // prints e.g. 3

    // change some data
    ....
    manager.flush();
    logger.info("@version=" + persistedDocument.getVersion()); 
    // prints e.g. 4

    ....
    // load document from jpa once again
    persistedDocument = manager.find(Document.class, id);

    logger.info("@version=" + persistedDocument.getVersion()); 
    // prints e.g. 3  (!!)

    // change some data
    ....
    manager.flush();
    // Throws OptimisticLockException !!
    // ...Document@1fbf7c8e] cannot be updated because it has changed or been deleted since it was last read

    ...
}

如果我在用

注释的方法中放置代码(更改数据并刷新实体bean)
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)

一切都按预期工作。

但为什么我的代码中的find()方法的第二次调用没有读取新的版本号?我希望在flush()和find()之后调用版本4。

1 个答案:

答案 0 :(得分:2)

毕竟它看起来像是在呼叫

 
/*SOME useful css */
.nopadding{ padding:0 !important;} /*use important because I Overwrite the css in same file.*/
.nomargin{margin:0 !important;}/*use important because I Overwrite the css in same file.*/
/*This is your main CSS*/
* {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
	font-family: 'Ubuntu', sans-serif;
}
header {
    background-color: #ff9900;
    text-align: center;
    color: black;
    font-size: 30px;
    height: 65px;
}
nav ul {
	overflow: hidden;
	list-style-type: none;
	text-align: center;
}
nav ul li a {
	display: block;
	padding: 20px 10px;
	font-size: 20px;
	text-decoration: none;
    background-color: #ff9900;
    color: black;
}
nav ul li a:hover {
	background-color: #e68a00;
}
nav ul li a:active {
	background-color: #ffa31a;
	color: white;
}







.row::after {
    content: "";
    clear: both;
    display: block;
}

/* For mobile phones: */
[class*="col-"] {
    float: left;
    padding: 15px;
    width: 100%;
}



@media only screen and (min-width: 600px) {

    /* For tablets: */
    .col-m-1 {width: 8.33%;}
    .col-m-2 {width: 16.66%;}
    .col-m-3 {width: 25%;}
    .col-m-4 {width: 33.33%;}
    .col-m-5 {width: 41.66%;}
    .col-m-6 {width: 50%;}
    .col-m-7 {width: 58.33%;}
    .col-m-8 {width: 66.66%;}
    .col-m-9 {width: 75%;}
    .col-m-10 {width: 83.33%;}
    .col-m-11 {width: 91.66%;}
    .col-m-12 {width: 100%;}
}
@media only screen and (min-width: 768px) {

    /* For desktop: */
    .col-1 {width: 8.33%;}
    .col-2 {width: 16.66%;}
    .col-3 {width: 25%;}
    .col-4 {width: 33.33%;}
    .col-5 {width: 41.66%;}
    .col-6 {width: 50%;}
    .col-7 {width: 58.33%;}
    .col-8 {width: 66.66%;}
    .col-9 {width: 75%;}
    .col-10 {width: 83.33%;}
    .col-11 {width: 91.66%;}
    .col-12 {width: 100%;}
}

解决了这个问题。我认为分离对象应该做同样的事情,但在我的情况下只调用clear()确实解决了问题。

更多调查结果:

毕竟调用方法detach()和flush()形成服务层似乎不是一个好主意。我这样做了,因为在我离开我的业务方法将这个id返回给客户端之前,我想得到我的实体的新版本ID。在这种情况下,我改变了我的策略,并删除了所有“坏事”。分离和刷新我的实体bean。代码变得更加清晰,毕竟代码复杂性大大降低。

当然,entityManager现在可以正常运行。如果我在一个事务中多次查询同一个实体bean,则entityManager返回正确的更新版本。

所以我自己的问题的答案是:只要没有充分的理由使用它们,就把方法刷新()和clear()。