且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如果相似的行存在,如何避免创建新行?

更新时间:2023-02-17 17:32:29


虽然行存在,但它创建了一个新行


这并不完全正确。这不仅仅是休眠自动决定创建一个新用户。 Hibernate正在做你的代码告诉它的内容:
$ b $ ul

  • addMyUsers()中,你创建新的名字()新的用户(),并且你既不给这些预先存在的ID。您已使这些对象看起来像新的,而不是预先存在的对象。

  • addMyUser()中,您调用 session.merge(user)。 Hibernate看到这些对象没有ID - 所以它将它合并并赋予它们NEW状态。当交易清空& hibernate生成SQL来创建新的ID并将对象存储为新记录。


    如果您想确定对象是否为pre - 存在,并在可能的情况下对以前的记录进行操作:


    1. 获取要使用的字段(例如,从Web表单) - 在你的情况下,这包括det字段。

    2. 查看数据库中是否存在该记录。使用hibernate通过 session.find() session.get()检索对象,在你的情况下使用 det字段。

    3. 如果找不到对象,那么然后创建一个新对象。

    4. 对于检索到的对象,可以选择分离(例如通过 session.clear())修改会话中的对象。新创建的对象已处于分离状态。

    5. 修改对象(设置它的字段)。

    6. 如果对象已分离,请通过 session.merge()进行连接。合并适用于既有的分离对象(通过检索获得)和新的分离对象(通过 new< Object>())。或者,对于预先存在的分离对象,您可以调用 session.update();对于新的分离对象,您可以调用 session.save()/ persist ()

    7. 刷新/提交交易。



  • 您错过了(2)。 p>

    I need to configure hibernate to avoid creating duplicate rows, (although the row exists it creates a new one, and since only one filed is set it set all the rest to NULL)

    Lets say I have a row as following

    id des    index age
    1  MyName 2     23
    

    Although I just set MyName as des and it already exists in the Name table hibernate create a new row as following

    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
    

    When I want to sa . So I have added the following annotation to my class but it crossed the Entity, and dynamicUpdate.

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

    I used @DynamicUpdate as well, although hibernate accept it but still I have the same problem.

    Is there any other method to do it ? Version of my hibernate is as following

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

    *Based on Ray's comment blew, By assigning a value to Id of child class it works properly but how about if I do not have the ID? do I have to do a select to find the id first ? Is there any method to force hibernate to do it automatically r based on values of child class rahter than doing a separate select to find the id? *

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

    although the row exists it creates a new one

    That's not quite right. It's not just hibernate automatically deciding to create a new user. Hibernate is doing what your code tells it to:

    • In addMyUsers(), you create new Name() and new User(), and you give neither of these a pre-existing ID. You have made these objects look like new ones, rather than pre-existing ones to be updated.
    • In addMyUser(), you call session.merge(user). Hibernate sees the objects have no ID - so it merges them and assigns them the NEW status. When the transaction is flushed & committed, hibernate generates SQL to create new IDs and store the objects as new records.

    If you want to determine whether an object is pre-existing, and operate on the previous record where possible:

    1. Obtain the fields that you want to use (e.g. from a web form) - in your case, this includes "det" field.
    2. See if the record already exists in the database. Retrieve the object using hibernate via session.find() or session.get(), in your case using the "det" field.
    3. If the object cannot be found, then create a new object.
    4. For retrieved objects, you can optionally detach the object from the session before modification, (e.g. via session.clear()). Newly created objects are already in a detached state.
    5. Modify the object (set it's fields).
    6. If the object is detached, then attach via session.merge(). Merge works for both pre-existing detached objects (obtained via retrieval) and new detached objects (via new <Object>()). Alternatively, for pre-existing detached objects you can call session.update() and for new detached objects you can call session.save()/persist().
    7. flush/commit the transaction.

    You're missing (2).