web-dev-qa-db-ja.com

jdbiは挿入時に自動生成された値を返します

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;

顧客テーブルと参照テーブルのデータを1つのSQLクエリで読み取るcustomerDAOの実装を開始しましたが、それほど複雑ではありませんでした。

@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値を読み取る方法が見つからなかったため、これも機能しません。

参照を正しく保つことができるように、この問題にどのように取り組むことができるかについてのアイデアはありますか?

21
Alexander Köb

気にしないでください、少なくとも自動生成されたキーを取得する方法は、その間に解決策を見つけました:

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

これは、1つのステートメントに対して生成されたキーを取得するために機能しますが、私の場合は、複数のクエリを実行し、正しい参照を手動で入力する必要があります。

このプロセスを単純化して参照を自動的に入力する方法を誰かが知っている場合でも、私はそれについて聞きたいと思います。

ありがとう。

39
Alexander Köb

Postgresを使用すると、1つだけでなく、すべての自動生成された値を取得できます。

@SqlUpdateを@SqlQueryに変更し、INSERT ... RETURNING *を使用して、アドレスのマッパーがあると仮定して、これを行うことができます。

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