dropwizard - partir - insertar id autoincrement sql
jdbi devuelve valor autogenerado en inserciones (2)
Con postgres puede obtener no solo uno, sino incluso todos los valores generados automáticamente.
Puede hacerlo cambiando @SqlUpdate a @SqlQuery y utilizando INSERT ... RETURNING *, suponiendo que tiene un asignador de direcciones:
@SqlQuery("insert into addresses (line_1) values (''address line 1'') returning *")
public Address insertAddress(@BindBean Address address);
Estoy jugando con Dropwizard y quiero crear una aplicación REST que tenga varias relaciones de clave externa en las entidades.
Por ejemplo, dadas las siguientes 3 tablas:
-- 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;
Comencé a implementar un customerDA que lee los datos de la tabla de clientes y las tablas a las que se hace referencia con una consulta SQL, que no fue muy complicado:
@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);
}
(En aras de la brevedad, me salto el asignador, ya que esa no es mi pregunta real)
Ahora quiero insertar un nuevo cliente, tengo todos los datos necesarios, incluidos los datos que pertenecen a las tablas a las que se hace referencia.
No pude encontrar una manera de ejecutar consultas múltiples con anotaciones jdbi, por lo que pensé: tengo que crear un método DAO para cada una de las tablas e insertar los datos desde java, actualizando manualmente las referencias de las claves externas.
Pero también esto no funciona porque no pude encontrar una manera de leer el valor de ID generado automáticamente después de una inserción.
¿Alguna idea de cómo podría abordar este problema para poder mantener las referencias correctas?
No importa, encontré la solución mientras tanto, al menos cómo obtener la clave generada automáticamente:
en su DAO, agregue la anotación @GetGeneratedKeys, asegúrese de que su valor de retorno del método coincida con el valor de la clave generada:
@SqlUpdate("insert into addresses (line_1) values (''address line 1'')")
@GetGeneratedKeys
public long insertAddress();
En su recurso, entonces, simplemente puede utilizar el valor de retorno:
long id = customerDAO.insertAddress();
System.out.println("Found id " + id);
Esto funciona para obtener la clave generada para una declaración, sin embargo, en mi caso, todavía necesito hacer múltiples consultas y completar las referencias correctas manualmente.
Si alguien tuviera una idea de cómo podría simplificar este proceso y dejar que las referencias se completen automáticamente, todavía me interesaría saberlo.
Gracias.