JPA 标准 Updatequery 没有真正更新任何东西
JPA criteria Updatequery not really updating anything
我无法让 Updatequery
真正发生更新。做个简单的测试 class:
@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)
我可以看到更新查询和绑定正确(?):
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>
...
所有测试都发生在一个事务中,因此在您第一次加载实体时,它们会存储在会话缓存中。第二次加载它们时,它们只是再次从会话缓存中检索:更新查询绕过缓存。
您需要在再次获取实体之前清除 EntityManager。
我无法让 Updatequery
真正发生更新。做个简单的测试 class:
@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)
我可以看到更新查询和绑定正确(?):
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>
...
所有测试都发生在一个事务中,因此在您第一次加载实体时,它们会存储在会话缓存中。第二次加载它们时,它们只是再次从会话缓存中检索:更新查询绕过缓存。
您需要在再次获取实体之前清除 EntityManager。