当前位置: 首页 > 知识库问答 >
问题:

JOOQ-从POJO插入时排除id字段

李经国
2023-03-14

是否可以直接从POJO中使用Jooq将新记录插入到PostgreSQL数据库中?POJO扩展了一个具有id字段的通用标识类,而不在insert语句中包含id?

@Data
public abstract class PersistenceIdentity {
    @Id
    @Column(name = "id", unique = true, nullable = false, precision = 7, insertable = false)
    private Integer id;

    @Column(name = "created_date")
    private LocalDateTime createdDate;

    public abstract Table<R> getJooqTable();
}

@Data
public class SocialNetwork extends PersistenceIdentity {

    @Column(name = "name")
    private String name;

    @Override
    public Table<SocialNetworkRecord> getJooqTable() {
        return Tables.SOCIAL_NETWORK;
    }

}
CREATE TABLE "social_network" (
    id              SERIAL NOT NULL PRIMARY KEY,
    created_date    TIMESTAMP DEFAULT now(),
    name            TEXT NOT NULL
);
public <T extends PersistenceIdentity> T insertRecord(T record) {
    Record newRecord = db.newRecord(record.getJooqTable(), record);
    if (newRecord instanceof UpdatableRecord) {
        ((UpdatableRecord) newRecord).store();
    }

    return newRecord.into(record);
}

问题是,Jooq在insert语句中包含id,然后我当然得到一个null值约束。我不希望在它是新记录时插入它,但我希望在它返回记录时(插入后)、更新时以及select语句中包含它。

我不能简单地排除id,因为以后我需要它来轻松地绕过@onetomany/@manytoone的一些限制。

我不想为每个POJO插入特定的值(这就是为什么我们使用@column进行注释)。

Jooq不尊重@column中的@id或insertable=false参数吗?

有人能解释一下吗?

每个请求编辑1,下面是jOOQ生成的表对象的相关片段。我不确定这对于我所要做的事情是否正确(即允许数据库生成ID),但我认为nextval('social_network_id_seq'::regclass)可以实现这一点。

@Generated(
    value = {
        "http://www.jooq.org",
        "jOOQ version:3.9.1"
    },
    comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class SocialNetwork extends TableImpl<SocialNetworkRecord> {

    /**
     * The column <code>public.social_network.id</code>.
     */
    public final TableField<SocialNetworkRecord, Integer> ID = createField("id", org.jooq.impl.SQLDataType.INTEGER.defaultValue(org.jooq.impl.DSL.field("nextval('social_network_id_seq'::regclass)", org.jooq.impl.SQLDataType.INTEGER)), this, "");

}
<column>
    <table_catalog></table_catalog>
    <table_schema>public</table_schema>
    <table_name>social_network</table_name>
    <column_name>id</column_name>
    <data_type>integer</data_type>
    <character_maximum_length>0</character_maximum_length>
    <numeric_precision>32</numeric_precision>
    <numeric_scale>0</numeric_scale>
    <ordinal_position>1</ordinal_position>
    <column_default>nextval('social_network_id_seq'::regclass)</column_default>
</column>
<table_constraint>
    <constraint_catalog></constraint_catalog>
    <constraint_schema>public</constraint_schema>
    <constraint_name>social_network_pkey</constraint_name>
    <constraint_type>PRIMARY KEY</constraint_type>
    <table_catalog></table_catalog>
    <table_schema>public</table_schema>
    <table_name>social_network</table_name>
</table_constraint>
<table_constraint>
    <constraint_catalog></constraint_catalog>
    <constraint_schema>public</constraint_schema>
    <constraint_name>2200_17431_1_not_null</constraint_name>
    <constraint_type>CHECK</constraint_type>
    <table_catalog></table_catalog>
    <table_schema>public</table_schema>
    <table_name>social_network</table_name>
</table_constraint>
<table_constraint>
    <constraint_catalog></constraint_catalog>
    <constraint_schema>public</constraint_schema>
    <constraint_name>2200_17431_3_not_null</constraint_name>
    <constraint_type>CHECK</constraint_type>
    <table_catalog></table_catalog>
    <table_schema>public</table_schema>
    <table_name>social_network</table_name>
</table_constraint>
<key_column_usage>
    <column_name>id</column_name>
    <constraint_catalog></constraint_catalog>
    <constraint_schema>public</constraint_schema>
    <constraint_name>social_network_pkey</constraint_name>
    <ordinal_position>0</ordinal_position>
    <table_catalog></table_catalog>
    <table_schema>public</table_schema>
    <table_name>social_network</table_name>
</key_column_usage>

编辑2我的SocialNetwork Jooq生成的表对象没有getidentity()方法,但是它有getprimarykey()方法,如果有帮助的话,我的SocialNetworkRecord类有两个构造函数:

public SocialNetworkRecord() {
    super(SocialNetwork.SOCIAL_NETWORK);
}

/**
 * Create a detached, initialised SocialNetworkRecord
 */
public SocialNetworkRecord(Integer id, Timestamp createdDate, String name) {
    super(SocialNetwork.SOCIAL_NETWORK);

    set(0, id);
    set(1, createdDate);
    set(2, name);
}

共有1个答案

邴兴为
2023-03-14

jOOQ的工作方式,有两个元素值得解释:

Record newRecord = db.newRecord(record.getJooqTable(), record);

此调用对此很方便:

Record newRecord = db.newRecord(record.getJooqTable());
newRecord.from(record);

record.from(对象)将使用record.set(字段,对象)记录中的所有值复制到newrecord,这再次设置记录的内部record.changed(字段)标志。

您的电话:

((UpdatableRecord) newRecord).store();

将考虑执行的相关insertupdate语句的所有changed()字段。这里的基本原理是,人们有时希望显式地设置主键值,而不是让标识为他们生成值。即使主键上存在标识,有时也可能需要重写其值。因此,SQL标准数据库(例如Oracle 12c)支持两种指定标识的方式:

-- This can be overridden
GENERATED BY DEFAULT AS IDENTITY

-- This can never be overridden
GENERATED ALWAYS AS IDENTITY

(MySQL的auto_increment或PostgreSQL的serial类型的工作方式相同)

- `NOT NULL` constraint
- `GENERATED BY DEFAULT AS IDENTITY`

然后,jOOQ将省略考虑插入/更新的标识值。

请注意,直到jOOQ版本3.9.2之前,XMLGenerator中存在一个bug/缺失特性,该特性生成要导入的XML文件:https://github.com/jOOQ/jOOQ/issues/6141。此bug导致未生成任何身份信息。

如果由于某种原因,无法获得jOOQ元模型来反映NOT NULL约束和DEFAULT子句,则可以通过在Recordd.from(Object)调用后使用Recordd.reset(Field)重置标识值来解决此限制:

Record newRecord = db.newRecord(record.getJooqTable(), record);
newRecord.reset(identityColumn);
((UpdatableRecord) newRecord).store();

代码生成器具有生成合成标识的特性。例如,如果所有标识列都称为ID,则可以这样写:

<!-- fully qualified -->
<syntheticIdentities>.*?\.ID</syntheticIdentities>

或者这个:

<!-- unqualified -->
<syntheticIdentities>ID</syntheticIdentities>
 类似资料:
  • 问题内容: 我想表达以下声明: 子选择返回一行,其中包含两列(和),需要将其插入到target中。这样做的原因是,是的主键。是指(外键)。 这可能吗? 问题答案: 我不确定首先使用哪种SQL方言是否可能通过,但是您当然可以使用以下方式表达这种查询: 或与jOOQ

  • 因此,我希望使用将一些记录懒洋洋地取入POJOs,如下所示: 我当然可以做以下事情,但感觉不对: 谢了!

  • ****TransactionHistoryBO POJO** ** 事务历史响应pojo

  • 我有一个像上面一样的pojo 用于创建json请求对象的代码如下: 我只是想通过不删除任何上述代码从args中删除userIds。 提前谢谢。

  • 问题 在代码生成期间,我在配置到自定义POJO的映射时遇到了一些问题。 问题 我已经实现了,但想知道如何注册它以在代码生成阶段使用,或者即使这是可能的? 更多上下文 我喜欢波霍斯 如果有帮助,我将使用DefaultConfiguration对象(一个bean)配置jOOQ: 然后对于代码生成,我在gradle中配置它: 我确信这两种配置之间存在脱节,但我无法从文档中了解如何同步这些配置。理想情况下

  • 我试图在我的表中插入一条新记录 DSLContext类型中的方法newRecord(Table, Object)不适用于参数(String, ModelBook) 但是和这个一样:http://www.jooq.org/doc/2.5/manual/sql-execution/fetching/pojos/ 所以我不能做: