[英]Updating values in an Embeddable class
這就是我想要做的...我有一個人
@Entity
@Table(name = "PERSON",
uniqueConstraints = {
@UniqueConstraint(columnNames = {"SSN"})
}
)
@DynamicInsert(true)
@DynamicUpdate(true)
@SelectBeforeUpdate(true)
public class Person implements java.io.Serializable {
private static final long serialVersionUID = 6732775093033061190L;
@Version
@Column(name = "OBJ_VERSION")
private Timestamp version;
@Id
@Column(name = "SSN", length = 12, nullable = false, insertable = true, updatable = true)
private String ssn;
@Column(name = "LAST_NAME", length = 50, nullable = false, insertable = true, updatable = true)
private String lastName;
@Column(name = "FIRST_NAME", length = 30, nullable = false, insertable = true, updatable = true)
private String firstName;
@Column(name = "MIDDLE_NAME", length = 30, nullable = true, insertable = true, updatable = true)
private String middleName;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "person", cascade = CascadeType.ALL)
private Passport passport;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Citizenship> citizenship = new HashSet<>();
// Getters and setters left out for brevity
每個人可以有一個護照
@Entity
@Table(name = "PASSPORT",
uniqueConstraints = {
@UniqueConstraint(columnNames = {"SSN", "PASSPORT_NUMBER"})
}
)
@DynamicInsert(true)
@DynamicUpdate(true)
@SelectBeforeUpdate(true)
public class Passport implements java.io.Serializable {
private static final long serialVersionUID = 6732775093033061190L;
@Version
@Column(name = "OBJ_VERSION")
private Timestamp version;
@Id
@Column(name = "SSN", length = 12, nullable = false, insertable = true, updatable = true)
private String ssn;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "SSN")
@MapsId
private Person person;
@Column(name = "EXPIRATION_DATE", nullable = true, insertable = true, updatable = false)
private GregorianCalendar expirationDate;
@Column(name = "ISSUING_COUNTRY", nullable = true, insertable = true, updatable = false)
private String issuingCountry;
@Column(name = "PASSPORT_NUMBER", nullable = false, insertable = true, updatable = false)
private String passportNumber;
// Getters and setters left out for brevity
這項工作,每個人可以擁有一個Passport,並且Passport.ssn分配了Person.ssn的值。 這樣做是因為SSN是唯一標識符,並且避免了對鏈接表的需求。
每個人也可以擁有公民身份
@Entity
@Table(name = "CITIZENSHIP")
@DynamicInsert(true)
@DynamicUpdate(true)
@SelectBeforeUpdate(true)
public class Citizenship implements java.io.Serializable {
private static final long serialVersionUID = 6732775093033061190L;
@Version
@Column(name = "OBJ_VERSION")
private Timestamp version;
@EmbeddedId
private CitizenshipId citizenshipId;
@Column(name = "DATE_OF_CITIZENSHIP")
private GregorianCalendar dateOfCitizenship;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "SSN")
@MapsId("ssn")
private Person person;
// Getters and setters left out for brevity
我已經成功添加了一個有護照的人和一個沒有護照的人。 我添加了第三人,護照和雙重國籍
// This person has a passport and is a dual citizen.
person = new Person();
person.setSsn("654-89-7531");
person.setFirstName("Lois");
person.setLastName("Lane");
passport = new Passport();
passport.setExpirationDate(new GregorianCalendar());
passport.setIssuingCountry("USA");
passport.setPassportNumber("987654");
Set<Citizenship> citizenshipSet = new HashSet<>();
CitizenshipId citizenshipId = new CitizenshipId();
citizenshipId.setCountry("USA");
Citizenship c = new Citizenship();
c.setDateOfCitizenship(new GregorianCalendar());
c.setCitizenshipId(citizenshipId);
c.setPerson(person);
citizenshipSet.add(c);
citizenshipId = new CitizenshipId();
citizenshipId.setCountry("CAN");
c = new Citizenship();
c.setDateOfCitizenship(new GregorianCalendar());
c.setCitizenshipId(citizenshipId);
c.setPerson(person);
citizenshipSet.add(c);
person.setPassport(passport);
passport.setPerson(person);
session.saveOrUpdate(person);
for(Citizenship citizen : citizenshipSet) {
session.saveOrUpdate(citizen);
}
session.flush();
session.clear();
對我來說,這看起來很奇怪/效率低下,但確實可以工作(需要改進的提示)。 但是根據需要,Person.ssn被納入公民身份。 這是問題所在:
具有雙重國籍的人目前在美國和加拿大具有國籍。 讓我們假設這是錯誤的,並且此人在美國和墨西哥擁有公民身份,這意味着CitizenshipId.country需要從“ CAN”更改為“ MEX”。 我嘗試了很多類似的代碼變體
Criteria citCriteria = session.createCriteria(Citizenship.class);
citCriteria.add(Restrictions.eq("citizenshipId.ssn", "654-89-7531"));
List<Citizenship> citizenship = citCriteria.list();
for(Citizenship c : citizenship) {
if("CAN".equalsIgnoreCase(c.getCitizenshipId().getCountry())) {
session.evict(c);
c.getCitizenshipId().setCountry("MEX");
session.saveOrUpdate(c);
session.flush();
session.clear();
}
}
啟用“ show_sql”后,即使我在調試時看到值更改,也不會執行更新。 我確實嘗試了一個evict(),然后設置了國家/地區,然后設置了saveOrUpdate,從而創建了一個新條目(我認為可以)。
ew ...問題是:當該類用作EmbeddedId時,如何更新Embeddable類中的值? 我覺得我已經接近了,但只想念一件事...
謝謝。
添加CitizenshipID供參考
@Embeddable
public class CitizenshipId implements Serializable {
private static final long serialVersionUID = 6732775093033061190L;
String ssn;
String country;
// Omitted getters, setters, constructors, hashcode, and equals
你有沒有嘗試過:
if("CAN".equalsIgnoreCase(c.getCitizenshipId().getCountry())) {
session.evict(c);
c.getCitizenshipId().setCountry("MEX");
c.getPerson().getCitizenship().add(c); // TRY ADDING THIS
session.saveOrUpdate(c);
session.flush();
session.clear();
}
if("CAN".equalsIgnoreCase(c.getCitizenshipId().getCountry())) {
// TRY ADDING THIS ------------------------
//session.evict(c);
CitizenshipId cid = new CitizenshipId();
cid.setSsn(c.getCitizenshipId().getSsn();
cid.setCountry("MEX");
c.setCitizenshipId(cid); // references new CID -- should issue update
// -----------------------------------------
session.saveOrUpdate(c);
session.flush();
session.clear();
}
由於API中的說明,我刪除了.evict:
從會話緩存中刪除該實例。 對實例的更改將不會與數據庫同步。 如果關聯是用cascade =“ evict”映射的,則此操作將級聯到關聯的實例。
主題如何更新Spring-JPA中與主鍵相關的值與 Dan上面發布的內容有關,即有關使用舊對象ID創建新對象的內容。 但是,主題Hibernate-更新表中的主鍵'id'列確實表明Hibernate不允許更新主鍵。
此處的目標是創建一個具有SSN(可能具有護照)和公民身份的人。 SSN旨在作為主鍵,因此我將Person映射到Passport and Citizenship,並將SSN用作JoinColumn。
護照的人是一對一的關系,所以這不是問題。
人與人之間的關系是一對多的關系。 這種關系意味着我必須創建一個可嵌入的ID。 為了使每個Citizenship唯一,使用SSN和Country創建了可嵌入的類CitizenshipId。
使用可接受的Hibernate答案-更新表中的主鍵“ id”列,我更改了
Criteria citCriteria = session.createCriteria(Citizenship.class);
citCriteria.add(Restrictions.eq("citizenshipId.ssn", "654-89-7531"));
List<Citizenship> citizenship = citCriteria.list();
for(Citizenship c : citizenship) {
if("CAN".equalsIgnoreCase(c.getCitizenshipId().getCountry())) {
session.evict(c);
c.getCitizenshipId().setCountry("MEX");
session.saveOrUpdate(c);
session.flush();
session.clear();
}
}
至
Query query=session.createQuery("update Citizenship set country = :country1 where ssn = :ssn and country = :country2")
.setString("country1", "MEX").setString("ssn", "654-89-7531").setString("country2", "CAN");
query.executeUpdate();
並且確實發生了更新。 無法通過典型代碼進行更新(使用條件來獲取數據,對其進行更新,然后調用saveOrUpdate),但是能夠通過查詢進行更新對我來說並沒有多大意義。 我知道,密鑰管理比最好的情況更多地留給數據庫,但是當使用唯一值(例如SSN)時,就不需要另一個密鑰。 如果在代碼中沒有生成策略的情況下標識了ID,則說明可以更新ID ... JMHO。
感謝Dan的想法。 希望本主題及其參考對其他人有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.