我有兩個簡單的物體
//Address @Entity
@OneToOne(fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "user_id", nullable = false)
private User user;
和
//User @Entity
@OneToOne(mappedBy = "user", orphanRemoval = true)
Address address;
但我無法用新地址更新用戶。
第一種方法:
Address address = new Address();
User user = userRepository.findByUsername("someemail");
address.setUser(user);
addressRepository.save(address);
代碼運行良好,但插入陳述句已完成,現在我在資料庫中有兩個地址記錄,這會導致將來出現例外。
第二種方法
Address address = new Address();
User user = userRepository.findByUsername("someemail");
address.setUser(user);
user.setAddress(address); //added this line
addressRepository.save(address);
現在它拋出例外
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
第三種方法
Address address = new Address();
User user = userRepository.findByUsername("someemail");
address.setUser(user);
user.setAddress(address);
userRepository.save(user); //added this
addressRepository.save(address);
新例外:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing
臨時解決方案
這個解決方案有效,但它是我撰寫的最丑陋的代碼,而且我也不知道它為什么有效。如果有人有更好的答案,我將標記為解決方案。
首先向物體添加級聯
@OneToOne(mappedBy = "user", orphanRemoval = true, cascade = CascadeType.ALL)
Address address;
然后使用這個更新:
User user = userRepository.findByUsername("someemail");
if (user.getAddress() != null) {
addressRepository.delete(user.getAddress());
user.setAddress(address);
address.setUser(user);
userRepository.save(user);
} else {
address.setUser(user);
addressRepository.save(address);
}
uj5u.com熱心網友回復:
//地址@Entity
@OneToOne(fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "user_id", nullable = false) private User user;和
//User @Entity @OneToOne(mappedBy = "user", orphanRemoval = true) Address address;
根據上面的代碼,您已經宣告該物體Address將是具有相關映射的物體User。因此,您Address在資料庫中的表有一個額外的欄位user_id,可以將此地址與相關用戶映射。
檢查您的第一種方法
Address address = new Address(); <--- new address entity created
User user = userRepository.findByUsername("someemail"); <--- user retrieved from DB
address.setUser(user); <----New address record in address table is set up to have the relevant user
addressRepository.save(address);
你應該反過來做
還將@Transactional添加到執行以下代碼的方法中
Address address = new Address();
User user = userRepository.findByUsername("someemail");
if (user.getAddress() != null) {
Address oldAddress = user.getAddress();
oldAddress.setUser(null);
}
user.setAddress(address);
userRepository.save(user);
為此,您必須在您的User物體中修改
@OneToOne(mappedBy = "user", orphanRemoval = true, cascade = CascadeType.ALL)
Address address;
現在,當您執行上述代碼時,先前的地址物體將被更新以具有對 a 的null參考,user這樣orphanRemoval它將完成它的作業并將其從資料庫中洗掉,而新地址將被持久化并與相關用戶鏈接。
uj5u.com熱心網友回復:
這是最終的作業答案
//address entity, no cascade non sense
@JoinColumn(name = "user_id", nullable = false, unique=true)
private User user;
和
//User @Entity
@OneToOne(mappedBy = "user", orphanRemoval = true)
Address address;
然后更新參考
if (user.getAddress() != null) {
user.setAddress(null);
userRepository.save(user);
}
address.setUser(user);
addressRepository.save(address);
uj5u.com熱心網友回復:
你和托馬斯·愛迪生有很多共同點……
User user = userRepository.findById(1L).get();
user.getAddress().setSomething("YYY");
addressRepository.save(user.getAddress());
不過,真的,你不應該為自己制造問題。如果這樣做,請列印 SQL 以查看發生了什么。
User user = userRepository.findById(1L).get();
addressRepository.delete(user.getAddress());
user = userRepository.save(user);
addressRepository.save(Address.builder().something("YYY").user(user).build());
我會以不同的方式做到這一點。
// Address
@OneToOne(mappedBy = "address")
private User user;
// User
@OneToOne
private Address address;
和
User user = userRepository.findById(2L).get();
user.setAddress(addressRepository.save(Address.builder().something("YYY").user(user).build()));
userRepository.save(user);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/462560.html
上一篇:JPA查詢在postgres中作業,但在API中重新調整了一些空欄位
下一篇:如何處理建構式中的可為空引數?
