Supongamos que tengo una tabla en una base de datos Postgresql:
CREATE TABLE FOO ( ID INT PRIMARY KEY NOT NULL, NAME CHAR(50) UNIQUE NOT NULL );que es creado por hibernación en una aplicación Spring Boot
y quiero insertar lo siguiente:
INSERT INTO FOO (ID, NAME) VALUES (1, "BAR"); INSERT INTO FOO (ID, NAME) VALUES (2, "BAZ"); INSERT INTO FOO (ID, NAME) VALUES (3, "ZIP");como datos iniciales cuando están en la siguiente clase:
@Component public class SeedDB implements CommandLineRunner { private final FooRepository fooRepository; @Autowired public SeedDB(FooRepository fooRepository) { this.fooRepository = fooRepository; } @Override public void run(String... strings) throws Exception { fooRepository.save(new Foo("bar")); fooRepository.save(new Foo("baz")); fooRepository.save(new Foo("zip")); } }todo esto solo para decir que funciona muy bien siempre que la base de datos esté vacía. pero si está configurado para ejecutarse cada vez que la aplicación gira, entonces la restricción única provoca el siguiente error:
Caused by: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [ukjsk1parw92chjvhsj49tl7492]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement ... Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "ukjsk1parw92chjvhsj49tl7492" Detail: Key (name)=(bar) already exists.lo cual tiene sentido, supongo. Lo que estoy tratando de averiguar es si hay una manera, sin envolver cada línea en un bloque if/else o try/catch, para intentar la inserción sin tener en cuenta el resultado.
el problema es que no puedo usar el enfoque de hibernación de crear y soltar porque hay otras tablas que no se pueden perder en el esquema.
Puede usar aquí try catch block, pero creo que, en el caso de campos unique , debemos verificar cada vez en la base de datos (el campo existe o no) antes de persistir en nuestra entidad para que devuelva la seguridad, y creo que es una mejor manera de hágalo, porque en caso de intentar capturar si manejaremos ConstraintViolationException ( Implementation of JDBCException indicating that the requested DML operation resulted in a violation of a defined integrity constraint. ), esta excepción puede ocurrir en any case of DML operation resulted in a violation , Por lo tanto, será mejor asegurarse de que nuestro archivo sea único, debemos verificarlo antes de persistir, si existirá una entidad, podemos mostrar un mensaje fácil de usar para el usuario o el registro.
en su caso, el código le gustará:
if(fooRepository.countByFiledName("bar")==0) { fooRepository.save(new Foo("bar")); }