EntityManager.merge()的意外行为

时间:2013-02-27 09:09:25

标签: jpa-2.0 eclipselink glassfish-embedded

我使用带有junit(4.11)的嵌入式glassfish(3.1.2.2)和JDK 1.7,尽管我的源和目标设置为1.6(maven-compiler-plugin配置)。

以下是我的代码:

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(按预期方式):

INSERT INTO PERSON (ID, STATUS, USERNAME, VERSION) VALUES (?, ?, ?, ?)
    bind => [1, status, username, 1]

第2步生成以下SQL(按预期方式):

UPDATE PERSON SET STATUS = ?, VERSION = ? WHERE ((ID = ?) AND (VERSION = ?))
    bind => [Away, 2, 1, 1]

第3步不会生成任何SQL,但它不会抛出任何异常,这是我所期待的,因为“用户名”注释为 @Column(...,可更新= false)。 print(...)方法打印以下输出:

  

合并(用户名更改):人[id = 1,版本= 2,用户名= UsErNaMe,状态=离开]

这次merge()操作已经更新了用户名,但没有更新版本。此外,现在数据库与EntityManager缓存不同步。

这是预期的,还是EclipseLink中的错误?

更新

预期结果是上述步骤3的例外情况。

更新

已提交错误here

1 个答案:

答案 0 :(得分:1)

您将该列标记为不可更新,并且EclipseLink检测到对您指定要合并的人所做的唯一更改是用户名。但是不得更新用户名。因此它不会发出任何SQL更新查询。

如果将列标记为不可更新,则不应更新它。

因此,为了清楚起见,您观察到的行为就是预期的行为。