Hibernate ошибка повторяющееся значение ключа нарушает ограничение уникальности

I have the following problem

@Entity
@Table(name="tb_pessoa", schema="public")
@Inheritance(strategy = InheritanceType.JOINED)
public class Pessoa implements Serializable {
   private static final long serialVersionUID = 1L;

   @Id
   @SequenceGenerator(name = "tb_pessoa_id_seq", sequenceName = "tb_pessoa_id_seq", schema="public")
   @GeneratedValue(strategy = GenerationType.AUTO, generator = "tb_pessoa_id_seq")
   @Column(name = "id", nullable = false)
   private Integer id;

   ...

@Entity  
@Table(name="tb_pessoafisica", schema="public")
@PessoaFisicaAnnotation
@PrimaryKeyJoinColumn(name = "id")
public class PessoaFisica extends Pessoa implements Serializable {
   private static final long serialVersionUID = 1L;

   @Column(name = "email")
   private String email;

   ...

Assuming the Pessoa table has records with id 1 to 500. When I run the code below:

PessoaFisica pessoaFisica = new PessoaFisica();
pessoaFisica.setEmail("teste@123.com");

...

em.persist(pessoa);

It’s happening the following error:

17:26:13,613 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-1) ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
    Detalhe: Key (id)=(438) already exists.
17:26:13,614 WARN  [com.arjuna.ats.arjuna] (http--10.36.1.49-8180-1) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffff7f000101:-7f6ae4e3:558080ed:4f, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization@331af73a >: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
  Detalhe: Key (id)=(438) already exists.

why is trying to use the id 438 and not 501???

Does anyone know what might be happening?

thank you very much

CREATE TABLE tb_pessoa
(
    id integer NOT NULL,
    CONSTRAINT tb_pessoa_pkey PRIMARY KEY (id)
)

CREATE TABLE tb_pessoafisica
(
    email character varying(64) NOT NULL,
    CONSTRAINT tb_pessoafisica_pkey PRIMARY KEY (id),
    CONSTRAINT fkee8c050f70415778 FOREIGN KEY (id)
        REFERENCES tb_pessoa (id) MATCH SIMPLE
)

CREATE SEQUENCE tb_pessoa_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 500
  CACHE 1;

Log Hibernate:

07:50:52,463 INFO  [stdout] (http--10.36.1.49-8180-2) Hibernate: 
07:50:52,463 INFO  [stdout] (http--10.36.1.49-8180-2)     select
07:50:52,464 INFO  [stdout] (http--10.36.1.49-8180-2)         nextval ('public.tb_pessoa_id_seq')
07:50:52,497 INFO  [stdout] (http--10.36.1.49-8180-2) Hibernate: 
07:50:52,498 INFO  [stdout] (http--10.36.1.49-8180-2)     insert 
07:50:52,499 INFO  [stdout] (http--10.36.1.49-8180-2)     into
07:50:52,499 INFO  [stdout] (http--10.36.1.49-8180-2)         public.tb_pessoa
07:50:52,500 INFO  [stdout] (http--10.36.1.49-8180-2)         (id) 
07:50:52,500 INFO  [stdout] (http--10.36.1.49-8180-2)     values
07:50:52,501 INFO  [stdout] (http--10.36.1.49-8180-2)         (?)
07:50:52,519 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-2) SQL Error: 0, SQLState: 23505
07:50:52,521 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--10.36.1.49-8180-2) ERROR: duplicate key value violates unique constraint "tb_pessoa_pkey"
    Detalhe: Key (id)=(438) already exists.

Есть таблица в БД PostgreSql. У этой таблицы есть ограничение на уникальность для id. Сохраняю сущности в БД посредством Hibernate.

Код Entity:

@Entity
@Table(name = "cinema_movie")
public class Cinema_Movie {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "cinema_id")
    private String cinemaId;

    @Column(name = "movie_id")
    private String movieId;

Геттеры и сеттеры, плюс конструктор прилагаются. Не писал для сокращения кода.

Код сохранения в БД:

public void save() {
        CinemaMovie cinema_movie = new CinameMovie();
        cinema_movie.setCinemaId("random");
        cinema_movie.setMovieId("random")
        session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        session.save(cinema_movie); 
    }

Ну и в HibernateSessionFactoryUtil ничего особенного нет:

public static SessionFactory getSessionFactory() {
        logger.debug("Start method getSessionFactory() at HibernateSessionFactoryUtil.class");
        if (sessionFactory == null) {
            try {
                Configuration configuration = new Configuration().configure();
                configuration.addAnnotatedClass(Cinema_Movie.class);
                StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
                sessionFactory = configuration.buildSessionFactory(builder.build());

            } catch (Exception e) {
                logger.error("Error at method getSessionFactory() at HibernateSessionFactoryUtil.class: ", e);
            }
        }
        logger.debug("End of method getSessionFactory() at HibernateSessionFactoryUtil.class");
        return sessionFactory;
    }

И соответственно, метод save() вызывается переодически в разное время в программе. Изменения в БД в данную таблицу вносились руками, удалялись некоторые записи, т.к. программа только на стадии разработки.

Вопрос в следующем:

Как происходит генерация уникальных значений в Hibernate, и почему переодически я получаю ошибку:

ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности

?

А так же, как избежать данной ошибки, т.е. чтобы Hibernate точно гененрировал уникальные ID, которых еще нет в БД? Только дополнительной проверкой? Или сделать другой primary key, который самому генерировать? Или же есть какая то возможность исключения такой ошибки с помощью инструментов Hibernate?

Postgres handles auto incrementing a little differently than MySQL does. In Postgres, when you create the serial field, you are also creating a sequence field that is keeping track of the id to use. This sequence field is going to start out with a value of 1.

When you insert a new record into the table, if you don’t specify the id field, it will use the value of the sequence, and then increment the sequence. However, if you do specify the id field, then the sequence is not used, and it is not updated, either.

I’m assuming that when you moved over to Postgres, you seeded or imported some existing users, along with their existing ids. When you created these user records with their ids, the sequence was not used, and therefore it was never updated.

So, if, for example, you imported 10 users, you have users with ids 1-10, but your sequence is still at 1. When you attempt to create a new user without specifying the id, it pulls the value from the sequence (1), and you get a unique violation because you already have a user with id 1.

To resolve the issue, you need to set your users_id_seq sequence value to the MAX(id) of your existing users. You can read this question/answer for more information on resetting the sequence, but you can also try something like (untested):

SELECT setval(pg_get_serial_sequence('users', 'id'), coalesce(max(id)+1, 1), false) FROM users;

FYI, this is not an issue in MySQL because MySQL automatically updates the auto increment sequence to the largest column value when a value is manually inserted into the auto incrementing field.

This question have been asked by several people but my problem seems to be different.
Actually I have to merge same structured tables from different databases in postgresql into a new DB. What I am doing is that I connect to remote db using dblink, reads that table in that db and insert it into the table in the current DB like below

INSERT INTO t_types_of_dementia SELECT * FROM dblink('host=localhost port=5432 dbname=snap-cadence password=xxxxxx', 'SELECT dementia_type, snapid FROM t_types_of_dementia') as x(dementia_type VARCHAR(256),snapid integer);

First time this query runs fine, but when I run it again or try to run it with some other remote database’s table: it gives me this error

ERROR: duplicate key value violates unique constraint
«t_types_of_dementia_pkey»

I want that this new tables gets populated by entries of others tables from other dbs.
Some of the solutions proposed talks about sequence, but i am not using any

The structure of the table in current db is

CREATE TABLE t_types_of_dementia(
    dementia_type VARCHAR(256),
    snapid integer NOT NULL,
    PRIMARY KEY (dementia_type,snapid)
);

P.S. There is a specific reason why both the columns are used as a primary key which may not be relevant in this discussion, because same issue happens in other tables where this is not the case.

This question have been asked by several people but my problem seems to be different.
Actually I have to merge same structured tables from different databases in postgresql into a new DB. What I am doing is that I connect to remote db using dblink, reads that table in that db and insert it into the table in the current DB like below

INSERT INTO t_types_of_dementia SELECT * FROM dblink('host=localhost port=5432 dbname=snap-cadence password=xxxxxx', 'SELECT dementia_type, snapid FROM t_types_of_dementia') as x(dementia_type VARCHAR(256),snapid integer);

First time this query runs fine, but when I run it again or try to run it with some other remote database’s table: it gives me this error

ERROR: duplicate key value violates unique constraint
«t_types_of_dementia_pkey»

I want that this new tables gets populated by entries of others tables from other dbs.
Some of the solutions proposed talks about sequence, but i am not using any

The structure of the table in current db is

CREATE TABLE t_types_of_dementia(
    dementia_type VARCHAR(256),
    snapid integer NOT NULL,
    PRIMARY KEY (dementia_type,snapid)
);

P.S. There is a specific reason why both the columns are used as a primary key which may not be relevant in this discussion, because same issue happens in other tables where this is not the case.

Главная

Я также столкнулся с этой проблемой, и решение, предложенное @adamo, было в основном правильным решением. Однако мне пришлось потратить много времени на детали, поэтому сейчас я пишу новый ответ, чтобы сэкономить это время для других.

Коробка

Мой случай был следующим: была таблица, которая была заполнена данными с помощью приложения. Теперь новую запись нужно было вставить вручную через SQL. После этого последовательность не синхронизировалась, и больше нельзя было вставить записи через приложение.

Решения

Как упоминалось в ответе @adamo, последовательность необходимо синхронизировать вручную. Для этого необходимо название последовательности. Для Postgres имя последовательности можно определить с помощью команды PG_GET_SERIAL_SEQUENCE. В большинстве примеров используются имена таблиц в нижнем регистре. В моем случае таблицы были созданы промежуточным программным обеспечением ORM (например, Hibernate или Entity Framework Core и т. Д.), И все их имена начинались с заглавной буквы.

В электронном письме от 2004 г. (ссылке) Я получил правильный намек.

(Предположим для всех примеров, что Foo это имя таблицы и Foo_id соответствующий столбец.)

Команда для получения названия последовательности:

SELECT PG_GET_SERIAL_SEQUENCE('"Foo"', 'Foo_id');

Итак, имя таблицы должно быть в двойных кавычках, окруженных одинарными кавычками.

1. Убедитесь, что последовательность не синхронизирована.

SELECT CURRVAL(PG_GET_SERIAL_SEQUENCE('"Foo"', 'Foo_id')) AS "Current Value", MAX("Foo_id") AS "Max Value" FROM "Foo";

Когда Current Value меньше чем Max Value, ваша последовательность не синхронизирована.

2. Исправление

SELECT SETVAL((SELECT PG_GET_SERIAL_SEQUENCE('"Foo"', 'Foo_id')), (SELECT (MAX("Foo_id") + 1) FROM "Foo"), FALSE);

Wondering how to fix PostgreSQL Error code 23505? We can help you.

One of the most common error codes with the PostgreSQL database is 23505. It can be seen along with the error message “duplicate key violates unique constraint”

Here at Bobcares, we often handle requests from our customers to fix similar PostgreSQL errors as a part of our Server Management Services. Today we will see how our support engineers fix this for our customers.

How PostgreSQL Error code 23505

At times we may get the following message when trying to insert data into a PostgreSQL database:

ERROR:  duplicate key violates unique constraint

This happens when the primary key sequence in the table we’re working on becomes out of sync. And this might likely be because of a mass import process.

Here we have to manually reset the primary key index after restoring it from a dump file.

To check whether the values are out of sync, we can run the following commands:

SELECT MAX(the_primary_key) FROM the_table;

SELECT nextval('the_primary_key_sequence');

If the first value is higher than the second value, our sequence is out of sync.

We can back up our PG database and then run the following command:

SELECT setval('the_primary_key_sequence', (SELECT MAX(the_primary_key) FROM the_table)+1);

This will set the sequence to the next available value that’s higher than any existing primary key in the sequence.

To Resolve this error in VMware

When vpxd process crashes randomly after upgrading to vCenter Server 6.5 with the following error:

ODBC error: (23505) - ERROR: duplicate key value violates unique constraint "pk_vpx_guest_disk";
Panic: Unrecoverable database error. Shutting down VC

In the vpxd.log file, we can see entries similar to the one given below:

error vpxd[7F8DD228C700] [Originator@6876 sub=InvtVmDb opID=HB-host-476@72123-38e1cc31] >[VpxdInvtVm::SaveGuestNetworkAndDiskToDb] Failed to insert guest disk info for VM id = 976because of database error: "ODBC error: >(23505) - ERROR: duplicate key value violates unique constraint "pk_vpx_guest_disk";

–> Error while executing the query” is returned when executing SQL statement “INSERT INTO VPX_GUEST_DISK (VM_ID, PATH, CAPACITY, >FREE_SPACE) VALUES (?, ?, ?, ?)”
And in the postgresql.log file, you see entries similar to the one given below:

VCDB vc ERROR: duplicate key value violates unique constraint "pk_vpx_guest_disk"

VCDB vc DETAIL: Key (vm_id, path)=(976, /tmp) already exists.
Steps to fix the error are given below:

vCenter Services can be given a service restart. If the starting fails to initialize the service and shows the same crash reason, we can fix this by removing the impacted guest disk entry from vCenter Server Database. This information is safe to remove as it will be re-populated from the host.

For vCenter Server with vPostgres database:

1. First, take a snapshot of the vCenter Server machine before proceeding.

2. Then connect the vCenter Database.

3. And identify the guest disk entry using the following query:

select FROM vc.vpx_guest_disk where vm_id=<vm id> and path='/tmp';For example:

select FROM vc.vpx_guest_disk where vm_id='976' and path='/tmp';

4. For deleting the duplicate value we can use the following command:

delete FROM vc.vpx_guest_disk where vm_id=<vm id> and path='/tmp';

For example:

select FROM vc.vpx_guest_disk where vm_id='976' and path='/tmp';

We can get the VM id  from the vpxd.log error entry

5. Finally start the Service.

We can delete the snapshot after observing the stability of the vCenter Server.

[Need assistance? We can help you]

Conclusion

In short, we saw how our Support Techs fix PostgreSQL Error code 23505 for our customers.

PREVENT YOUR SERVER FROM CRASHING!

Never again lose customers to poor server speed! Let us help you.

Our server experts will monitor & maintain your server 24/7 so that it remains lightning fast and secure.

GET STARTED

var google_conversion_label = «owonCMyG5nEQ0aD71QM»;

#postgresql #postgresql-9.3

#postgresql #postgresql-9.3

Вопрос:

При выполнении запроса на ОБНОВЛЕНИЕ мы получили следующее сообщение об ошибке:

 ERROR:  duplicate key value violates unique constraint "tableA_pkey"
DETAIL:  Key (id)=(47470) already exists.
 

Однако наш запрос на ОБНОВЛЕНИЕ не влияет на первичный ключ. Вот упрощенная версия:

 UPDATE tableA AS a
SET
    items = (
        SELECT array_to_string(
            array(
                SELECT b.value
                FROM tableB b
                WHERE b.a_id = b.id
                GROUP BY b.name
            ),
            ','
        )
    )
WHERE
    a.end_at BETWEEN now() AND  now() - interval '1 day';
 

Мы убедились, что последовательность первичных ключей уже синхронизирована:

 d tableA_id_seq
 

Что приводит к:

     Column     |  Type   |          Value           
--------------- --------- --------------------------
 sequence_name | name    | tableA_id_seq
 last_value    | bigint  | 50364
 start_value   | bigint  | 1
 increment_by  | bigint  | 1
 max_value     | bigint  | 9223372036854775807
 min_value     | bigint  | 1
 cache_value   | bigint  | 1
 log_cnt       | bigint  | 0
 is_cycled     | boolean | f
 is_called     | boolean | t
 

Ищем максимальный индекс таблицы:

 select max(id) from tableA;
 

Мы получили меньшее значение:

   max  
-------
 50363
(1 row)
 

Есть ли у вас какие-либо идеи о причинах такого поведения? Если мы исключим проблемный идентификатор, это сработает.

Еще один странный момент заключается в том, что замена предыдущего ОБНОВЛЕНИЯ на:

 UPDATE tableA AS a
SET
    items = (
        SELECT array_to_string(
            array(
                SELECT b.value
                FROM tableB b
                WHERE b.a_id = b.id
                GROUP BY b.name
            ),
            ','
        )
    )
WHERE a.id = 47470;
 

Это работает хорошо. Мы что-то упускаем?

РЕДАКТИРОВАТЬ: триггеры

У меня нет пользовательских триггеров в этой таблице:

 SELECT t.tgname, c.relname
FROM pg_trigger t
JOIN pg_class c ON t.tgrelid = c.oid
WHERE
    c.relname = 'tableA'
    AND
    t.tgisinternal = false
;
 

Которое не возвращает строки.

Примечание: я использую psql (PostgreSQL) версии 9.3.4.

Комментарии:

1. Есть ли какие-либо триггеры в таблице обновлений?

2. Какова версия вашего сервера Postgres?

3. @pozs: я добавил запрос, который я сделал, чтобы найти триггеры. У меня 16 в этой таблице. Есть ли у вас какие-либо просьбы предоставить более подробную информацию об этом?

4. @JonathanPetitcolas все определяемые пользователем ( WHERE pg_trigger.tgisinternal = FALSE ), которые запускаются до и после обновления, с телами функций триггеров.

5. Нет пользовательских триггеров. 🙁

Ответ №1:

Не совсем уверен, в чем причина. Однако удаление двух (не жизненно важных) записей, соответствующих уже существующим идентификаторам (?), решило проблему.

Комментарии:

1. Вероятно, вам следует принять свой собственный ответ, если он сработал для вас.

Есть три сущности
Город и Источник погоды ( они идентичны ):

public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(unique = true, nullable = false)
    private String cityName;

    public City(String cityName) {
        this.cityName = cityName;
    }
}

Погода:

public class Weather {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private LocalDateTime date;
    private double temp;
    private double humidity;
    private int pressure;
    private String weatherDescription;

    @ManyToOne
    @JoinColumn(name="weather_source_id")
    private WeatherSource weatherSource;

    @ManyToOne
    @JoinColumn(name="city_id")
    private City city;
}

При добавлении погоды с городом, который уже есть в городе получаем ошибку:

//выше получена погода
        w.setCity(new City("Rostov-on-Don"));
        w.setWeatherSource(new WeatherSource("openWeather"));
        weatherService.add(w);

ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности «uk_djnk44fptegbsu6drhc9xvlfj»

Подробности: Ключ «(city_name)=(Rostov-on-Don)» уже существует.
Как сделать, чтобы hibernate не пытался добавить запись в таблицу городов, если там уже есть нужный город?
Пробовал использовать в equals и hasCode только значение name. Неужели перед тем как добавить нужно просто из сервиса вытянуть город по имени и его уже добавлять к погоде? нельзя ли это сделать автоматически?

#java #postgresql #hibernate #spring-boot #jpa

#java #postgresql #впасть в спящий режим #пружинный ботинок #jpa

Вопрос:

Повторяющееся значение ключа нарушает ограничение уникальности после сохранения объекта @ManyToOne

Я попытался сохранить объект A, у которого есть другой объект B с уникальным именем поля с помощью spring-data. Если B уже существует в БД, то будет выдано исключение «дублирующее значение ключа нарушает уникальное ограничение «b_name_key». Подробно: Ключ (b_name)=(someName) уже существует.

 create table b
(
  b_id         serial primary key,
  b_name varchar(3) not null unique
);

create table a
(
  a_id            serial primary key,
  b_id      int references b (b_id) not null,
);


@Entity
@Getter
@Setter
public class B implements java.io.Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long b_id;
    @Column(name = "b_name", unique = true)
    private String bName;

    public B(String bName) {
        this.bName = bName;
    }

    public B() {}

    @Override
    public String toString() {
        return "...";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        B b = (B) o;
        return Objects.equals(bName, b.bName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(bName);
    }
}

@Entity
@Getter
@Setter
public class a implements java.io.Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long a_id;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "b_id")
    private B b;


    public a() {
    }

    public a(B b  ) {
        this.b = b;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        a a = (a) o;
        return Objects.equals(b, a.b)
    }

    @Override
    public int hashCode() {
        return Objects.hash(b);
    }
}


@Repository
public interface ARepository extends JpaRepository<Metastasis, Long> {}

@Controller
public class AController {

    private final ARepository aRepository;

    public AController(ARepository aRepository) {
        this.aRepository = aRepository;
    }

    @GetMapping("/test")
    public String showaddUserForm() {
        B b = new B("SomeName");
        A a = new A(b);
        aRepository.save(a);
        return "index";
    }
}

@SpringBootApplication
@EnableJpaRepositories(basePackages = "...repositories")
@EnableTransactionManagement
@EntityScan(basePackages = "....entities")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
 

Я получаю org.postgresql.util.PSQLException: ОШИБКА: повторяющееся значение ключа нарушает уникальное ограничение «b_name_key»
Подробно: ключ (b_name) = (SomeName) уже существует.

Ответ №1:

Это нормально. Поскольку a объект является новым, операция сохранения будет каскадно передана b объекту, который также является новым, и завершится неудачей, поскольку в базе данных уже есть запись с этим ключом.

Попробуйте что-то вроде:

 // find for B
B b = bRepository.findById(..);
// if not found, create one
if (b == null) {
   b = new B("SomeName");
} 
A a = new A(b);
aRepository.save(a);
 

Комментарии:

1. Почему спящий режим не может справиться с этим сам?

Понравилась статья? Поделить с друзьями:
  • Hiberfil sys что это ошибка
  • Hi что означает эта ошибка на стиральной машине самсунг
  • Hi press ошибка кариер что делать
  • Hi press ошибка кариер не заводится
  • Hi press ошибка кариер 1300 причина