java - JPA 标准 Updatequery 并未真正更新任何内容

标签 java hibernate jpa spring-data-jpa criteria-api

我无法通过 Updatequery 真正进行更新。有一个简单的测试类:

@Entity
@ToString(callSuper = true)
// query just for logging purposes
@NamedQuery(name="TestEntity.findAll", query="SELECT t FROM TestEntity t")
public class TestEntity {
    @Id
    @GeneratedValue
    private Long id;    
    private String message = "not altered";
}    

和一个测试:

@Slf4j
@DataJpaTest
@org.springframework.transaction.annotation.Transactional(propagation =
                                Propagation.NOT_SUPPORTED)
@RunWith(SpringRunner.class)
public class TestEntityUpdateTest {

    @PersistenceContext
    private EntityManager em;

    private void buildTestEntity(int i) {
        em.persist(new TestEntity());
    }

    private void log(Object o) {
        log.info("\n{}", o);
    }

    @Test
    @Transactional
    public void testUpdate() {
        IntStream.range(1, 4).forEach(this::buildTestEntity);
        TypedQuery<TestEntity> tq =
                em.createNamedQuery("TestEntity.findAll", TestEntity.class);

        // log inserted stuff
        log.info("\nINSERTED rows");
        tq.getResultList().forEach(this::log);

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaUpdate<TestEntity> update =
                    cb.createCriteriaUpdate(TestEntity.class);
        Root<TestEntity> from = update.from(TestEntity.class);
        update.set(from.get("message"), "ALTERED TEXT!");
        int i = em.createQuery(update).executeUpdate();

        log.info("\nUPDATED {} rows", i);
        // log updated stuff
        tq.getResultList().forEach(this::log);
    }

}

这一定是非常简单的事情,但我看不到什么?我还在每个可以想象到的地方尝试了 em.flush()。

是否应该有一些额外的 commit() 或某些 Spring 数据设置?

行插入正确。我可以看到相应的日志行,例如:

TestEntity(super=org.example.spring.entity.updatequery.TestEntity@230a73f2, id=1, message=not altered)

我可以看到更新查询和绑定(bind)正确(?):

Hibernate:
update
test_entity
set
message=?
.... org.hibernate.type.descriptor.sql.BasicBinder:65 - binding parameter [1] as [VARCHAR] - [ALTERED TEXT!]

但是更新后我没有看到变化,但是:

TestEntity(super=org.example.spring.entity.updatequery.TestEntity@230a73f2, id=1, message=not altered)

来自pom.xml的相关部分(要求更多):

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.2.RELEASE</version>
</parent>
...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>test</scope>
    </dependency>
...

最佳答案

您的所有测试都在单个事务中进行,因此第一次加载实体时,它们将存储在 session 缓存中。第二次加载它们时,它们只是再次从 session 缓存中检索:更新查询绕过缓存。

在再次获取实体之前,您需要清除 EntityManager。

关于java - JPA 标准 Updatequery 并未真正更新任何内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53248471/

相关文章:

java - 使用 String.replace() 替换斜杠即 "\"

java - 比较包含对象列表的同一类的两个对象

java - 内部异常 : com. mysql.jdbc.exceptions.jdbc4.CommunicationsException:通信链接失败

java - 用于选择特定列的 Spring Data JPA 规范

java - 我的 JPA/Hibernate 自定义类型有什么问题?

java - 适用于 Mac OSX Catalina 的 Android studio 3.5 在索引进程中崩溃

java - 如何建立 TCP 连接并将数据发送到 Android Virtual Device App

oracle - 如何迭代 JPA 查询结果而不将它们全部保留在内存中?

java - 在单个查询中使用 FK 更新现有 JPA 子实体

java - 如何在 ObjectDB JPA 数据库中保存 UTF-8 字符串?