Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Hibernate中使用saveOrUpdate()创建新记录,而不是更新现有记录_Java_Database_Hibernate_Orm - Fatal编程技术网

Java 在Hibernate中使用saveOrUpdate()创建新记录,而不是更新现有记录

Java 在Hibernate中使用saveOrUpdate()创建新记录,而不是更新现有记录,java,database,hibernate,orm,Java,Database,Hibernate,Orm,我有一个类用户 class User { int id; String name; } 其中,id是User.hbm.xml中的本机生成器,name是数据库中的主键 在我的数据库中,我保存了一些关于用户的信息 然后我想连接有关用户的此信息 例如,在我的数据库中,我有一行插入到用户值('Bill') Main.java User bill = new User(); bill.setName("Bill"); session.saveOrUpdate(bill); 此代码总是尝试将新

我有一个类用户

class User { 
  int id;
  String name;
}
其中,
id
User.hbm.xml
中的本机生成器,
name
是数据库中的主键

在我的数据库中,我保存了一些关于用户的信息

然后我想连接有关用户的此信息

例如,在我的数据库中,我有一行
插入到用户值('Bill')

Main.java

User bill = new User();
bill.setName("Bill");
session.saveOrUpdate(bill);

此代码总是尝试将新的
账单
行插入表中,而不是更新现有的
账单
行。

因此,Id不保存在数据库中

如果在Hibernate中将Id映射为标识符,为什么Id不是de DB中的主键

为什么不在数据库中的“Name”上设置一个唯一的约束,并在Id上创建一个主键约束?

您应该使用 更新时更新(对象),以及 会话。保存时保存(对象)

这段代码总是试图将账单插入数据库,而不是在数据库中存在关于账单的行时更新

从Hibernate核心文档部分:

saveOrUpdate()
执行以下操作:

  • 如果对象已经是持久的 在此会话中,什么也不做
  • 如果另一个对象与 会话具有相同的标识符throw 例外
  • 如果对象没有 标识符属性,
    save()
    it
  • 如果对象的标识符具有 分配给新实例化的 对象,
    save()
    it
  • 如果对象是 由
    ,以及 属性值是相同的值 分配给新实例化的 对象,
    save()
    it
  • 否则
    update()
    对象
当您这样做时:

User bill = new User();
bill.setName("Bill");
session.saveOrUpdate(bill);
这个新创建的实例没有分配任何标识符值,
saveOrUpdate()
save()
它,如文档所示。如果这不是您想要的,请将
名称
作为主键。

因此您需要:

User u1 = new User("Bill");
session.save(u1);
User u2 = new User("Bill");
session.saveOrUpdate(u2);
注意到u1和u2是同一张账单并且只存储一次吗?Hibernate无法知道这些账单是同一个人。它只查看用户u2的id,发现它没有设置,得出应该插入u2的结论,然后尝试并报告异常

SaveOrUpdate保存一个全新的对象和当前附加到会话的已加载对象。这是可行的(假设您在某处有一个findByName方法,并且还有另一个属性,比如说favoriteColor):

但那不是你想要的,对吗

由于实体具有代理主键和单独的业务键(通过唯一性约束强制),问题会变得更糟。如果没有id字段且只有名称作为主键,则可以使用merge()(有关saveOrUpdate vs merge的讨论,请参见):

但是你没有,你需要在id上强制PK约束,在name上强制唯一性。所以你需要一些不同的merge来做到这一点。大致来说,你会喜欢以下几点:

public User mergeByName(User user) {
    User merged;
    User candidate = findByName(user.getName());
    if (candidate != null) {
        user.setId(candidate.getId());
        merged = session.merge(user);
    } else {
        session.save(user);
        merged = user;
    }
    return merged;
}

第一个问题:如果需要获取名为“Bill”的用户。你会怎么做?这应该会给你一个想法

要更新,您需要具有与用户对象关联的标识。只设置name属性是没有帮助的。如果您想在不使用标识符的情况下进行更新,请使用HQL作为查询

Query query = session.createQuery("update User u set u.name = :newName where u.name=:name");
query.setString("name", "Bill");
query.setString("newName", "John");
query.executeUpdate();

如果名称字段是主键。然后,如果您多次设置相同的名称,它将如何创建新记录?可能是您对该概念理解不正确。

谢谢您的支持
id
是主键,
name
具有唯一的构造函数,我们有对象类User,例如:
User bill=new User()
和我们从keybord或网站获得的关于bill的属性,我的问题是:如果db中存在bill.name,我们调用update(),那么如何使saveOrUpdate()表示保存bill。是的,你说得对,但我希望hibernate的函数saveOrUpdate()能帮我完成这项工作。我可以在签入的地方编写saveOrUpdate(),选择数据库中是否存在
name
,然后调用save()或update()。我认为这不是一个好主意,也许hibernate有更好的解决方案,例如override equals(),在这里我们比较bussines key.Thx中的元素。对于您的依赖,我明白为什么我的程序总是尝试插入。因为我有一个更快更容易的id,所以我怎么能在不将名称作为主键的情况下做到这一点呢。我可以使用这样的额外选择:
User-bill=new-User();法案。集合名称(“法案”);bill.setId(func())
其中func()是一个函数,当带有
name='Bill'
的行不存在时,该函数的结果为空,否则返回此行的id号;没有select,我怎么做?职业开发者如何解决这个问题?@kunkanwan:我不知道该如何理解这个“职业开发者”。现在,这并不能激励我进一步帮助你。恐怕你不理解我。我的英语很差。在“Pro developer”一句中,我想知道如何在软件行业解决这个问题(我是一个没有经验的学生),因为我的简单功能加上额外的select不够好。如果我伤害了你,我很抱歉。@kunkanwan好的,没问题。明天我会再回答这个问题。@PascalThivent但若您将名称命名为PK,以后可能需要将其作为另一个表的FK,那个么新表中会有许多名称,和使用ID作为PK相比,这些名称会获得大量的DB
public User mergeByName(User user) {
    User merged;
    User candidate = findByName(user.getName());
    if (candidate != null) {
        user.setId(candidate.getId());
        merged = session.merge(user);
    } else {
        session.save(user);
        merged = user;
    }
    return merged;
}
Query query = session.createQuery("update User u set u.name = :newName where u.name=:name");
query.setString("name", "Bill");
query.setString("newName", "John");
query.executeUpdate();