EntityManager.merge()的异常行为 [英] Unexpected behaviour of EntityManager.merge()
问题描述
我将嵌入式玻璃鱼(3.1.2.2)与junit(4.11)和JDK 1.7一起使用,尽管我的源和目标设置为1.6(maven-compiler-plugin配置)。
I am using embedded glassfish (3.1.2.2) with junit (4.11), with JDK 1.7, though my source and target is set to 1.6 (maven-compiler-plugin configuration).
以下是我的代码:
Person.java
@Entity
public class Person implements Serializable {
private static final long serialVersionUID = 81398385247591972L;
@Id
@GeneratedValue
private Long id;
@Version
private Long version;
@Column(length = 15, nullable = false, unique = true, updatable = false)
private String username;
@Column(length = 50)
private String status;
// Constructors
// getters/setters
// hashCode, equals, toString
}
Service.java
@Stateless
public class Service {
@PersistenceContext(unitName = "ExamplePU", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
public Person add(Person person) {
em.persist(person);
return person;
}
public Person find(Long id) {
return em.find(Person.class, id);
}
public Person modify(Person person) {
return em.merge(person);
}
// some more code ...
}
ServiceTest.java
public class ServiceTest {
private static EJBContainer ejbContainer;
private static Service service;
// @BeforeClass, @AfterClass, @Before, @After
@Test
public void testMerge() {
Person person;
/* Step 1 */person = service.add(new Person("username", "status"));
print("Added : " + person);
person.setStatus("Away");
/* Step 2 */person = service.modify(person);
print("Merged (status change) : " + person);
person.setUsername("UsErNaMe");
/* Step 3 */person = service.modify(person);
print("Merged (username change) : " + person);
}
// Some more tests
}
步骤1 生成以下SQL(按预期方式):
Step 1 generates following SQL (as expected):
INSERT INTO PERSON (ID, STATUS, USERNAME, VERSION) VALUES (?, ?, ?, ?)
bind => [1, status, username, 1]
步骤2 生成以下SQL (如预期):
Step 2 generates following SQL (as expected):
UPDATE PERSON SET STATUS = ?, VERSION = ? WHERE ((ID = ?) AND (VERSION = ?))
bind => [Away, 2, 1, 1]
第3步不会生成任何SQL,但不会引发任何异常,这是我所期望的,因为用户名的注释为 @Column(...,updatable = false)。 print(...)方法显示以下输出:
Step 3 does not generate any SQL, but it does not throw any exception, which I am expecting, as the 'username' is annotated as @Column(..., updatable = false). The print(...) method prints following output:
已合并(用户名更改):Person [id = 1,version = 2, username = UsErNaMe,status = Away]
Merged (username change) : Person [id=1, version=2, username=UsErNaMe, status=Away]
这一次merge()操作已更新用户名,但未更新版本。另外,现在数据库与EntityManager缓存不同步。
This time the merge() operation has updated username, but not version. Also, now the database is out-of-sync with EntityManager cache.
这是预期的还是EclipseLink中的错误?
Is this expected, or bug in EclipseLink?
更新
预期结果是上述步骤3的例外。
Expected result is exception at Step 3 above.
更新
已提交错误此处。
推荐答案
您将该列标记为不可更新,并且将EclipseLink标记为不可更新检测到您告诉要合并的人的唯一更改是用户名。但是用户名一定不能更新。因此,它不会发出任何SQL更新查询。
You marked the column as non-updatable, and EclipseLink detects that the only change made to the person you tell it to merge is the user name. But the user name must not be updated. So it doesn't issue any SQL update query.
如果将某列标记为不可更新,则不应对其进行更新。
If you mark a column as non-updatable, you shouldn't update it.
因此,弄清楚,您观察到的行为就是预期的行为。
So, to make things clear, the behavior you observe is the expected behavior.
这篇关于EntityManager.merge()的异常行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!