【问题标题】:jdbi return autogenerated value on insertsjdbi 在插入时返回自动生成的值
【发布时间】:2014-10-01 03:40:49
【问题描述】:

我正在玩 dropwizard,我想构建一个在实体中具有各种外键关系的 REST 应用程序。

例如给定以下 3 个表:

-- table persons
CREATE TABLE PUBLIC.PERSONS(
    ID BIGINT DEFAULT NOT NULL AUTOINCREMENT,
    FIRST_NAME VARCHAR(255),
    LAST_NAME VARCHAR(255),
    BIRTHDAY DATE,
    ADDRESS_ID BIGINT NOT NULL,
    CREATED TIMESTAMP DEFAULT 'current_timestamp',
    MODIFIED TIMESTAMP
);
ALTER TABLE PUBLIC.PERSONS ADD CONSTRAINT PUBLIC.PK_PERSONS PRIMARY KEY(ID);

-- table customers
CREATE TABLE PUBLIC.CUSTOMERS(
    ID BIGINT DEFAULT NOT NULL AUTOINCREMENT,
    PERSON_ID BIGINT NOT NULL,
    STATUS_CODE VARCHAR(100) DEFAULT 'ACQUISITION' NOT NULL,
    CREATED TIMESTAMP DEFAULT 'current_timestamp',
    MODIFIED TIMESTAMP
);
ALTER TABLE PUBLIC.CUSTOMERS ADD CONSTRAINT PUBLIC.PK_CUSTOMERS PRIMARY KEY(ID);

-- table addresses
CREATE TABLE PUBLIC.ADDRESSES(
    ID BIGINT DEFAULT NOT NULL AUTOINCREMENT,
    LINE_1 VARCHAR(255),
    LINE_2 VARCHAR(255),
    ZIP VARCHAR(255),
    CITY VARCHAR(255),
    COUNTRY_CODE VARCHAR(3),
    PHONE VARCHAR(255),
    FAX VARCHAR(255),
    CREATED TIMESTAMP DEFAULT 'current_timestamp',
    MODIFIED TIMESTAMP
);
ALTER TABLE PUBLIC.ADDRESSES ADD CONSTRAINT PUBLIC.PK_ADDRESSES PRIMARY KEY(ID);

-- and following forign key constraints:
ALTER TABLE PUBLIC.PERSONS ADD CONSTRAINT 
    PUBLIC.FK_PERSON_ADDRESS FOREIGN KEY(ADDRESS_ID) 
    REFERENCES PUBLIC.ADDRESSES(ID) ON DELETE SET NULL NOCHECK;

ALTER TABLE PUBLIC.CUSTOMERS ADD CONSTRAINT 
    PUBLIC.FK_CUSTOMER_PERSON FOREIGN KEY(PERSON_ID) 
    REFERENCES PUBLIC.PERSONS(ID) ON DELETE SET NULL NOCHECK;

我已经开始实现一个customerDAO,它通过一个SQL查询读取客户表和引用表的数据,这不是很复杂:

@RegisterMapper(CustomerResultMapper.class)
public interface CustomerDAO {

    @SqlQuery("select p.id as person_id, "
            + "p.first_name, p.last_name, p.birthday, "
            + "c.id as customer_id, c.status_code, "
            + "a.id as address_id, a.line_1, a.line_2, a.zip, "
            + "a.city, a.country_code, a.phone, a.fax "
            + "from customers c, persons p, addresses a "
            + "where c.id = :id "
            + "and c.person_id = p.id "
            + "and p.address_id = a.id")
    public Customer findCustomerById(@Bind("id") long id);
}

(为简洁起见,我跳过了映射器,因为这不是我的实际问题)

现在我想插入一个新客户,我有所有需要的数据,包括属于引用表的数据。

我找不到如何使用 jdbi 注释执行多个查询的方法,所以我想,我必须为每个表创建一个 DAO 方法并从 java 中插入数据,手动更新外键引用。

但这也不起作用,因为我找不到在插入后读取自动生成的 ID 值的方法。

知道如何解决这个问题,以便保持引用正确吗?

【问题讨论】:

    标签: dropwizard jdbi


    【解决方案1】:

    没关系,我在此期间找到了解决方案,至少如何获取自动生成的密钥:

    在你的 DAO 中,添加 @GetGeneratedKeys 注解,确保你的方法返回值与生成的键值匹配:

    @SqlUpdate("insert into addresses (line_1) values ('address line 1')")
    @GetGeneratedKeys
    public long insertAddress();
    

    然后,在您的资源中,您可以简单地使用返回值:

    long id = customerDAO.insertAddress();
    System.out.println("Found id " + id);
    

    这可以为一个语句获取生成的密钥,但是在我的情况下,我仍然需要进行多个查询并手动填写正确的引用。

    如果有人知道如何简化此过程并让参考文献自动填写,我仍然很想知道。

    谢谢。

    【讨论】:

    • 你试过让方法返回一个 List 吗?
    • 不,据我了解 GetGeneratedKeys 注释返回值 asint 或 long,您不能返回列表。
    • 查看 org.skife.jdbi.v2.GeneratedKeys,它可能会起作用。代码调用 java.sql.Statement.getGeneratedKeys() 返回一个 ResultSet。试一试。
    • 是的,它也可以工作,但仍然必须这样做:myInstance.id = dao.insert(myInstance);
    • @DavidPhillips List 不起作用,但 int[] 起作用
    【解决方案2】:

    使用 postgres,您不仅可以获得一个,甚至可以获得所有自动生成的值。

    您可以通过将 @SqlUpdate 更改为 @SqlQuery 并使用 INSERT ... RETURNING * 来实现,假设您有一个地址映射器:

    @SqlQuery("insert into addresses (line_1) values ('address line 1') returning *")
    public Address insertAddress(@BindBean Address address);
    

    【讨论】:

    • 这有多棒?
    • 这应该是答案。
    猜你喜欢
    • 1970-01-01
    • 2011-11-18
    • 2017-10-10
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多