简体   繁体   English

使用 Quarkus 和 Hibernate 通过 AttributeConverter 将 JSON 更改持久保存到数据库

[英]Persisting JSON change via AttributeConverter to database using Quarkus and Hibernate

I'm trying to persist changes to database in the following way:我正在尝试通过以下方式持久化对数据库的更改:

Entities实体

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转换器

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);
    }
}

Service服务

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);
    }
}

Configuration配置

<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&amp;characterEncoding=UTF-8&amp;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问题

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

What I've Tried我试过的

Here's some things I've tried:这是我尝试过的一些事情:

  • Adding entityManager.persist(entity);添加entityManager.persist(entity); to the end of modify function -> no change (expected)modify功能结束 ->无变化(预期)
  • Adding log entry to TestData.equals function -> no entry in the log将日志条目添加到TestData.equals函数 ->日志中没有条目
  • Adding entity.setData(entity.getData());添加entity.setData(entity.getData()); to the end of modify function -> no changemodify函数的结尾 ->没有变化
  • Changing JSON type to TEXT -> no change将 JSON 类型更改为 TEXT ->无变化
  • Manually starting and commiting transaction -> no change手动启动并提交事务 ->无变化
  • Adding 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谢谢

Versions版本

  • JRE 8杰瑞8
  • Quarkus 1.0.1.Final Quarkus 1.0.1.Final
  • Hibernate 5.4.9.Final休眠 5.4.9.Final
  • MySQL 8.0.18 MySQL 8.0.18

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM