[英]Persisting JSON change via AttributeConverter to database using Quarkus and Hibernate
I'm trying to persist changes to database in the following way:我正在尝试通过以下方式持久化对数据库的更改:
I have a JPA entity with JSON data type:我有一个具有 JSON 数据类型的 JPA 实体:
@Entity
public class TestEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@NotNull
@Convert(converter = TestConverter.class)
@Column(name = "data", columnDefinition = "JSON")
private TestData data;
...
}
With TestData
entity defined like this:使用这样定义的
TestData
实体:
public class TestData {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestData testData = (TestData) o;
return Objects.equals(value, testData.value);
}
@Override
public int hashCode() {
return Objects.hash(value);
}
}
Converter for TestData
is implemented like this: TestData
的转换器是这样实现的:
@Converter
public class TestConverter implements AttributeConverter<TestData, String> {
private static final Logger logger = LoggerFactory.getLogger(TestConverter.class);
private static final Jsonb jsonb = JsonbBuilder.create();
@Override
public String convertToDatabaseColumn(TestData attribute) {
logger.debug("To JSON: {}", attribute);
return jsonb.toJson(attribute);
}
@Override
public TestData convertToEntityAttribute(String dbData) {
logger.debug("From JSON: {}", dbData);
return jsonb.fromJson(dbData, TestData.class);
}
}
Finally I have a service which is trying to modify an existing entity in the database:最后我有一个试图修改数据库中现有实体的服务:
@ApplicationScoped
public class Service {
private static final Logger logger = LoggerFactory.getLogger(Service.class);
@Inject
public EntityManager entityManager;
@Transactional
public void modify(Long id) {
TestEntity entity = entityManager.find(TestEntity.class, id);
entity.getData().setValue("new");
logger.debug("Modified: {}", entity);
}
}
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:33003/test?sessionVariables=FOREIGN_KEY_CHECKS=0&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull" />
<property name="javax.persistence.jdbc.user" value="db-user" />
<property name="javax.persistence.jdbc.password" value="db-pass" />
<property name="javax.persistence.schema-generation.database.action" value="update"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.connection.provider_disables_autocommit" value="false"/>
The problem is that new
value is not persisted to the database.问题是
new
值没有保存到数据库中。 Here is what I see in the log:这是我在日志中看到的内容:
2019-11-30 12:19:40,065 DEBUG [org.acm.TestConverter] From JSON: {"value":"hello"}
2019-11-30 12:19:40,068 DEBUG [org.acm.TestConverter] To JSON: TestData{value='hello'}
2019-11-30 12:19:40,069 DEBUG [org.acm.TestConverter] From JSON: {"value":"hello"}
2019-11-30 12:19:40,071 DEBUG [org.acm.Service] Modified: TestEntity{id=2, data=TestData{value='new'}}
Here is the log file with hibernate logging turned on (too much to pase here so I'm posting a link): https://pastebin.com/1e3URx8W这是启用了休眠日志记录的日志文件(这里太多了,所以我发布了一个链接): https ://pastebin.com/1e3URx8W
Here's some things I've tried:这是我尝试过的一些事情:
entityManager.persist(entity);
entityManager.persist(entity);
to the end of modify
function -> no change (expected)modify
功能结束 ->无变化(预期)TestData.equals
function -> no entry in the logTestData.equals
函数 ->日志中没有条目entity.setData(entity.getData());
entity.setData(entity.getData());
to the end of modify
function -> no changemodify
函数的结尾 ->没有变化temp = entity.getData(); entity.setData(null); entity.setData(temp);
temp = entity.getData(); entity.setData(null); entity.setData(temp);
temp = entity.getData(); entity.setData(null); entity.setData(temp);
to the end of modify
function -> working the correct value is persisted to databasemodify
功能结束 - >工作正确的值被持久化到数据库Is there anything I'm missing here?我在这里缺少什么吗?
Thanks谢谢
Seems to me as if the update is pending in Hibernate's cache.在我看来,好像更新在 Hibernate 的缓存中挂起。 If you read the entity via the
EntityManager
or persist and flush ( EntityManager.persistAndFlush()
) after performing entity.setData(temp)
, the cache should get flushed and you should see your changes in the database.如果您在执行
entity.setData(temp)
后通过EntityManager
或持久化和刷新 ( EntityManager.persistAndFlush()
) 读取实体,缓存应该被刷新并且您应该在数据库中看到您的更改。
Quote from quarkus.io :引自quarkus.io :
JPA batches changes you make to your entities and sends changes (it's called flush) at the end of the transaction or before a query.
JPA 对您对实体所做的更改进行批处理,并在事务结束时或查询之前发送更改(称为刷新)。 This is usually a good thing as it's more efficient.
这通常是一件好事,因为它更有效率。 But if you want to check optimistic locking failures, do object validation right away or generally want to get immediate feedback, you can force the flush operation by calling entity.flush() or even use entity.persistAndFlush() to make it a single method call.
但是如果你想检查乐观锁定失败,立即进行对象验证或者通常想获得即时反馈,你可以通过调用 entity.flush() 强制刷新操作,甚至使用 entity.persistAndFlush() 使其成为一个方法称呼。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.