EntityManager.merge()的异常行为 [英] Unexpected behaviour of EntityManager.merge()

查看:279
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆