gpt4 book ai didi

Hibernate savOrUpdate 仅插入或更新

转载 作者:行者123 更新时间:2023-12-03 23:25:19 25 4
gpt4 key购买 nike

@Autowired
private SessionFactory sessionFactory;
public String getAccountsDetails(List<Account> accountList) {
Session session = sessionFactory.openSession();
for (Account account : accountList) {
int i = 0;
AccountDetails accountDetails = new AccountDetails();
accountDetails.setAccountsId(Long.parseLong(account.getId()));//LINE no -20
accountDetails.setName(account.getName());
accountDetails.setSubAccount(account.getAccountSubType());
session.saveOrUpdate(accountDetails);
if (++i % 20 == 0) {
session.flush();
session.clear();
}
}
session.getTransaction().commit();
session.close();
}

输出:

即使数据库中没有数据,这也总是运行更新。
   Hibernate: update name=?, subaccount=? where accounts_id=?
....

如果我在 LINE no-20 中评论帐户 ID,它总是运行插入。

hibernate :插入表测试...
……

dto类:
@Entity
@Table(name="test")
public class AccountDetails{
@Id
@GeneratedValue
@Column(name = "accounts_id")
private Long accountsId;

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

@Column(name = "subaccount")
private String subAccount;

}

询问:
甲骨文数据库:
 create table test (accounts_id NUMBER(10) NOT NULL PRIMARY KEY, 
name VARCHAR(100),
subaccount VARCHAR(100)
)

我的要求是如果数据库中没有数据,则插入否则更新。

编辑

我在我的 dto 中创建了一个新字段:
@Version
@Column(name = "version")
private long version;

并在 db 中创建了一个列作为版本号(100)。每当我运行应用程序时,它总是首先运行一个 updte 语句,然后它抛出 StaleObjectStateException 为:
Hibernate: update test set accountsubtype=?, accounttype=?, acctnum=?, active=?, currentbalance=?, currentbalancewithsubaccounts=?, description=?, fullyqualifiedname=?, name=?, subaccount=?, version=? where accounts_id=? and version=?
ERROR 2014-09-22 11:57:25,832 [[qbprojects].connector.http.mule.default.receiver.04] org.hibernate.event.def.AbstractFlushingEventListener: Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.trinet.mulesoft.quickbooks.dto.AccountDetails#63]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1932)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2576)

最佳答案

TL;博士

在您的情况下,saveOrUpdate()将产生:

  • 一个 INSERT如果 accountsIdnull .
  • 一个 UPDATE除此以外。

  • 这就是为什么当你有第 20 行( accountDetails.setAccountsId(...); )时,它是 UPDATE ing。

    最简单的方法可能是自己检查并调用 save()如果 accountsId尚不存在或 update()除此以外。

    细节:

    Automatic State Detection - 斜体是我写的:

    saveOrUpdate() does the following:

    • if the object is already persistent in this session, do nothing;
    • if another object associated with the session has the same identifier, throw an exception;
    • if the object has no identifier property, save() it;
      • No identifier property means no @Id or XML equivalent.
    • if the object's identifier has the value assigned to a newly instantiated object, save() it;
      • Notice that newly instantiated object is defined by the unsaved-value attribute.
      • In other words, this bullet says: if the @Id property value equals unsaved-value (see below), it is considered unsaved and then save() it.
      • This is your scenario. Notice that you are using unsaved-value=null because it is the default.
    • if the object is versioned by a <version> or <timestamp>, and the version property value is the same value assigned to a newly instantiated object, save() it;
      • This is the same as the item before, but with the <version> and <timestamp> properties instead of the @Id property.
      • Notice also both <version> and <timestamp> also have a unsaved-value=null attribute to define what is an unsaved or newly instantiated object.
    • otherwise update() the object


    有关 unsaved-value attribute 的更多详细信息(下面的引用来自 unsaved-value@Id/identifier 属性):

    unsaved-value (optional - defaults to a "sensible" value): an identifier property value that indicates an instance is newly instantiated (unsaved), distinguishing it from detached instances that were saved or loaded in a previous session.



    对于 Long标识符,“明智的”默认值很可能是 null .

    解决方法:

    如果只是想分配标识符,我们可以使用 <generator class="assigned"/>没关系。但你不想 两个 of worlds:有时分配并生成其他的。

    1 - 如上所述,一种选择是自己检查对象是否已经存在并调用 save()update()因此。

    2 - 另一个选项是 implement an Interceptor isTransient() method被覆盖。在这种方法中,您必须再次检查实体是否已经存在。优点:您只需执行一次(在 Interceptor 上)。缺点:嗯,它是一个 Interceptor你必须把它和它需要的一切连接起来。

    3 - 最后, docs hint有可能(我们必须确认)你可以通过使用生成器和设置属性 unsaved-value="undefined" 来做你想做的事。 .但是你必须求助于 XML 映射,因为你 can't set the unsaved-value through annotations :

    The unsaved-value attribute is almost never needed in Hibernate and indeed has no corresponding element in annotations.



    设置 unsaved-value通过 XML 将类似于:
    <id name="accountsId" column="accounts_id" type="long" unsaved-value="undefined">
    <generator class="auto" />
    </id>

    关于Hibernate savOrUpdate 仅插入或更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25952569/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com