2014-10-01 105 views
18

我在使用dropwizard,我想构建一个在实体中具有各种外键关系的REST应用程序。jdbi在插入时返回自动生成的值

例如给出如下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读取客户表中的D出现引用同一个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值的方法。

任何想法我可以如何解决这个问题,所以我可以保持引用正确?

回答

31

没关系,我发现在此期间解决方案,至少如何让自动生成的密钥:

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

这个工程来获取生成的科Ÿ对于一个语句,但在我的情况下,我仍然需要进行多个查询并手动填写正确的引用。

如果任何人有一个想法,我可以如何简化这个过程,并让参考资料自动填写,我仍然会有兴趣听到。

谢谢。

+0

您是否尝试过制作方法返回一个列表? – 2014-10-07 03:30:27

+0

不,据我了解,GetGeneratedKeys Annotation返回值asint或long,你不能返回一个列表。 – 2014-10-09 00:24:58

+2

看着org.skife.jdbi.v2.GeneratedKeys,它可能会起作用。代码调用返回ResultSet的java.sql.Statement.getGeneratedKeys()。试一试。 – 2014-10-09 17:49:49

13

有了postgres,你不仅可以获得一个,而且可以获得所有自动生成的值。

你可以通过改变@SqlUpdate到@SqlQuery和使用INSERT ... RETURNING *,假设这样做,你有地址的映射:

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

那真棒吗? – Christian 2016-02-02 12:54:26

+1

这应该是答案。 – 2016-09-30 14:49:37

+0

太棒了,让我的工作轻松+1 – BeginnersSake 2017-11-21 13:50:32