使用 JOOQ 从 POJO 设置字段为空

Posted

技术标签:

【中文标题】使用 JOOQ 从 POJO 设置字段为空【英文标题】:Set fields null from POJO using JOOQ 【发布时间】:2020-07-22 15:50:13 【问题描述】:

根据来自 JOOQ 博客的this entry,标题为“SQL DEFAULT 表达式和 POJO”的部分表明 POJO 中的任何空字段都会将该列设置为空,因为每个 Record.changed() 标志都将设置为真。

在实践中,我没有发现这种情况——如果 POJO 字段为空,并且我按照博客中的示例进行操作,则保留现有值。我想要将这些字段设置为空,但是如何使用 POJO 来做到这一点?

// Load the customer record from a POJO
CustomerRecord customer = ctx.newRecord(CUSTOMER, customerPojo);
customer.update();

// Expected behavior: null fields in customerPojo will set db values to null
// Actual behavior: null fields in customerPojo do not change values in db

编辑:这是使用 Jooq 3.11.10、Postgres 10.6。

创建客户脚本:

drop table if exists customers;
create table customers
(
    id         serial not null primary key,
    first_name text,
    last_name  text
);

客户类别:

@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Customer 

    private Integer id;
    private String firstName;
    private String lastName;

    public static Customers TAB = Customers.CUSTOMERS;
    static DSLContext ctx = PostgresSingleton.getMainCtx();

    public Customer store()
        CustomersRecord rec = ctx.newRecord(TAB, this);
        if(getId() == null) 
            rec.store();
        
        else 
            rec.update();
        
        rec.refresh();
        return rec.into(Customer.class);
    

测试(Spock/Groovy):

    def "Customer test"() 
        when: "save a new customer"
        Customer cust = Customer.builder().firstName("Phil").lastName("H").build().store()

        then: "ID populated"
        def custId = cust.getId()
        custId != null

        when: "null out last name"
        cust.toBuilder().lastName(null).build().store()

        then: "last name actually set to null"
        cust.getId() == custId
        cust.getFirstName() == "Phil"
        cust.getLastName() == null //fails, still is "H"
    

编辑 2:

看来.update() 调用实际上是在清空数据库中的字段!但是,之后的.into() 调用不会像预期的那样用空字段刷新 POJO。我验证了value for lastName 在.refresh() 之后为空,但into() 调用不会将该值设为空。

【问题讨论】:

能否将CUSTOMERCREATE TABLE 语句添加到您的问题、jOOQ 版本以及您正在使用的数据库方言中? @LukasEder 更新了请求的信息,以及 java 类和测试 我的测试有问题,请参阅下面的答案。感谢您关注@LukasEder 【参考方案1】:

嗯,这是一个 PEBKAC 错误——我没有将更新的结果存储回我的测试中的同一个对象中:

        when: "null out last name"
        cust.toBuilder().lastName(null).build().store() //not storing the result!

应该是:

        when: "null out last name"
        cust = cust.toBuilder().lastName(null).build().store()

很容易错过。

【讨论】:

啊!可变 API 与不可变 API! :-)

以上是关于使用 JOOQ 从 POJO 设置字段为空的主要内容,如果未能解决你的问题,请参考以下文章

在更新语句中排除空列 - JOOQ

从 POJO 到 Record 的 jOOQ 映射器

如果字段为空,则 Jooq fetchInto 具有默认值

如何使用默认构造函数和设置器生成 pojo

jOOQ 自定义 Pojo 和 DAO 生成

尝试使用 POJO 记录更新表时出现 Java jOOQ 问题