![](/img/trans.png)
[英]Persisting BigDecimal[][] to MySQL database by using JPA/Hibernate
[英]Persisting JSON change via AttributeConverter to database using Quarkus and Hibernate
我正在嘗試通過以下方式持久化對數據庫的更改:
我有一個具有 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;
...
}
使用這樣定義的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);
}
}
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);
}
}
最后我有一個試圖修改數據庫中現有實體的服務:
@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"/>
問題是new
值沒有保存到數據庫中。 這是我在日志中看到的內容:
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'}}
這是啟用了休眠日志記錄的日志文件(這里太多了,所以我發布了一個鏈接): https ://pastebin.com/1e3URx8W
這是我嘗試過的一些事情:
entityManager.persist(entity);
到modify
功能結束 ->無變化(預期)TestData.equals
函數 ->日志中沒有條目entity.setData(entity.getData());
到modify
函數的結尾 ->沒有變化temp = entity.getData(); entity.setData(null); entity.setData(temp);
temp = entity.getData(); entity.setData(null); entity.setData(temp);
到modify
功能結束 - >工作正確的值被持久化到數據庫我在這里缺少什么嗎?
謝謝
在我看來,好像更新在 Hibernate 的緩存中掛起。 如果您在執行entity.setData(temp)
后通過EntityManager
或持久化和刷新 ( EntityManager.persistAndFlush()
) 讀取實體,緩存應該被刷新並且您應該在數據庫中看到您的更改。
引自quarkus.io :
JPA 對您對實體所做的更改進行批處理,並在事務結束時或查詢之前發送更改(稱為刷新)。 這通常是一件好事,因為它更有效率。 但是如果你想檢查樂觀鎖定失敗,立即進行對象驗證或者通常想獲得即時反饋,你可以通過調用 entity.flush() 強制刷新操作,甚至使用 entity.persistAndFlush() 使其成為一個方法稱呼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.