Как избежать создания новой строки, если такая же строка существует?

Мне нужно настроить hibernate, чтобы избежать создания повторяющихся строк (хотя существует строка, она создает новую, и, поскольку установлена ​​только одна поданная, все остальное равно NULL)

Скажем, у меня есть строка, следующая за

id des    index age
1  MyName 2     23

Хотя я просто установил MyName как des, и он уже существует в спящем режиме таблицы имен создайте новую строку следующим образом

id des    index age
1  MyName 2     23
2  MyName Null  Null     << new row with null values will be created 
                            rather than updating the previous one

Когда я хочу  , Поэтому я добавил в мой класс следующую аннотацию, но она пересекла Entity и dynamicUpdate.

@org.hibernate.annotations.Entity(
  dynamicUpdate = true
)

Я использовал @DynamicUpdate, хотя спящий режим принимает его, но все же у меня такая же проблема.

Есть ли другой способ сделать это? Версия моего спящего режима выглядит следующим образом:

<dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>4.2.1.Final</version>
      <type>jar</type>
</dependency>

* Основываясь на комментариях Ray, назначая значение Id дочернего класса, он работает правильно, но как насчет того, если у меня нет идентификатора? мне нужно сделать выбор, чтобы сначала найти идентификатор? Есть ли способ заставить hibernate делать это автоматически r на основе значений дочернего класса rahter, чем отдельный выбор, чтобы найти идентификатор? *

User.Java

....
import org.hibernate.annotations.DynamicUpdate;

@Entity
@Table(name = "user") 
@DynamicUpdate
public class User implements Serializable {

  private int ID;
  private Name name;
  private String type;

  public User() {
  }

  @Id
  @GeneratedValue
  @Column(name = "id")
  public int getID() {
     return ID;
  }

  public void setID(int ID) {
     this.ID = ID;
  }

  @ManyToOne(cascade = CascadeType.ALL)
  public Name getName() {
     return name;
  }

  public void setName(Name name) {
    this.name = name;
  }

  .....

Name.Java

@Entity()
@Table(name = "Name")
public class Name implements Serializable {

private int id;
private String des;
private String index;
private String age;

public Name() {
}

@Id
@GeneratedValue
@Column(name="id", unique= true, nullable = false)
public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

.....

Model.java

public void addMyUsers(){
   Name name = new Name();
   name.setDes("MyName");
   While( ..... )
   {
       User user = new User();
       user.setName(name);
       user.setType(X);
       addUser(user);
   }
}

public void addUser(User user) {
        session = Util.getSession();

        session.beginTransaction();


        session.merge(user); 
        //session.saveOrUpdate(user);

        session.getTransaction().commit();

        session.close();
}

Ответ 1

хотя существует строка, она создает новый

Это не совсем правильно. Это не просто спящий режим, автоматически определяющий создание нового пользователя. Hibernate делает то, что говорит ваш код:

  • В addMyUsers() вы создаете new Name() и new User(), и вы не даете ни одному из них уже существующий идентификатор. Вы сделали эти объекты похожими на новые, а не на уже существующие, которые нужно обновить.
  • В addMyUser() вы вызываете session.merge(user). Hibernate видит, что объекты не имеют идентификатора, поэтому он объединяет их и присваивает им статус NEW. Когда транзакция сбрасывается и выполняется, hibernate генерирует SQL для создания новых идентификаторов и хранения объектов в качестве новых записей.

Если вы хотите определить, существует ли объект уже существующий, и, когда это возможно, работать с предыдущей записью:

  • Получите поля, которые вы хотите использовать (например, из веб-формы) - в вашем случае это включает в себя поле "det".
  • Посмотрите, существует ли запись в базе данных. Извлеките объект, используя спящий режим, через session.find() или session.get(), в вашем случае, используя поле "det".
  • Если объект не найден, создайте новый объект.
  • Для извлеченных объектов вы можете дополнительно отсоединить объект от сеанса до его модификации (например, через session.clear()). Новые созданные объекты уже находятся в отключенном состоянии.
  • Измените объект (установите его поля).
  • Если объект отсоединен, присоедините его через session.merge(). Слияние выполняется как для ранее существовавших отдельных объектов (полученных путем извлечения), так и для новых отдельных объектов (через new <Object>()). В качестве альтернативы для ранее существовавших отдельных объектов вы можете вызвать session.update(), а для новых удаленных объектов вы можете вызвать session.save()/persist().
  • выполнить флеш/зафиксировать транзакцию.

Вам не хватает (2).

Ответ 2

Его основной ключ, который играет здесь важную роль. вы должны использовать имя в качестве первичного ключа в этом случае, но я не буду предлагать вам это сделать, возьмите id в качестве первичного ключа.

Update:

Также в случае обновления идентификатор должен совпадать с записью, которую вы хотите обновить, но в случае вставки идентификатор должен быть нулевым, и вы получите его вставленным в db.

Ответьте на ваши комментарии:

вам нужно получить первичный ключ и отслеживать его следующим образом:

   session.update(recordEntity);// or save 
   int id=recordEntity.getId();

Ответ 3

вы должны сначала получить Имя, а не новое имя().

поэтому используйте меню "Поиск пользователя" /раскрывающийся список или что-то для пользователя, чтобы выбрать Имя, которое вы хотите, затем вы можете добавить, что Имя - новый пользователь .name

или если вы не хотите сначала искать имя (из тонкого воздуха # lol), вы не должны использовать User.name с типом Имя в первое место, используйте строку. но это более рискованно. и связь не может быть построена таким образом (вы должны запросить еще раз, если хотите получить Имя из Пользователь с именем x).

Ответ 4

Вы настроили этот способ. Пожалуйста, поделитесь ур кодом, если это не так.

@Entity
@Table(name = "example", catalog = "example_catalog")
@org.hibernate.annotations.Entity(
        dynamicUpdate = true
)

Ответ 5

Использование saveOrUpdate() не работало для меня в версии 4.3.Final Hibernate.

Записи "сохраняются" независимо от того, задан или действителен "id" (PK). Используйте save() или update() в зависимости от того, является ли запись "постоянной" (id! = Null и т.д.).

Я провел некоторое время, узнавая, так что, надеюсь, кому-то не придется.