2013-02-04 64 views
1

我想創建一個簡單的JPA 2.0樣式單向映射。對象模型簡單JPA 2.0簡單@OneToOne映射插入失敗

一個用戶可以有一個地址。

@Entity 
@Table(name = "USERS") 
public class User { 

@Id 
@SequenceGenerator(name="user_seq",sequenceName = "sequence",allocationSize=1) 
@GeneratedValue (generator="user_seq",strategy=GenerationType.SEQUENCE) 
@Column(name="userid") 
private Long userId; 

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

@OneToOne(cascade=CascadeType.PERSIST) 
@PrimaryKeyJoinColumn 
private Address address; 

public User() { 

} 

public Long getUserId() { 
    return userId; 
} 

public void setUserId(Long userId) { 
    this.userId = userId; 
} 


public String getEmailId() { 
    return emailId; 
} 

public void setEmailId(String emailId) { 
    this.emailId = emailId; 
} 


public Address getAddress() { 
    return address; 
} 

public void setAddress(Address address) { 
    this.address = address; 
} 


} 

@Entity 
@Table(name="address") 
public class Address { 
@Id 
@SequenceGenerator(name="address_seq",sequenceName =    "hibernate_sequence",allocationSize=1) 
@GeneratedValue (generator="address_seq",strategy=GenerationType.SEQUENCE) 
private long id; 


@Column(name="userid") 
private long userId; 

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



public Address() { 
    super(); 
} 



public Address (String completeAddress) { 
    super(); 
    this.completeAddress = completeAddress; 
} 



public long getId() { 
    return id; 
} 

public void setId(long id) { 
    this.id = id; 
} 

public long getUserId() { 
    return userId; 
} 

public void setUserId(long userId) { 
    this.userId = userId; 
} 

public String getCompleteAddress() { 
    return completeAddress; 
} 

public void setCompleteAddress(String completeAddress) { 
    this.completeAddress = completeAddress; 
} 



} 

這就是我正在嘗試創建一個新用戶並設置該用戶的地址。

EntityManager em = entityManagerFactory.createEntityManager(); 
EntityTransaction tx = em.getTransaction(); 
try { 
    tx.begin(); 
    User user = new User(); 
    user.setEmailId("test123"); 
    Address address = new Address(); 
    address.setCompleteAddress("some address"); 
    user.setAddress(address); 
    em.persist(user); 
    tx.commit(); 
} catch (Exception e) { 
    em.getTransaction().rollback(); 
} finally { 
    em.close(); 
} 

這是我的錯誤 -

[EL Warning]: 2013-02-04 16:00:03.376--UnitOfWork(1827795025)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException 
Internal Exception: org.postgresql.util.PSQLException: ERROR: insert or update on table "address" violates foreign key constraint "address_userid_fkey" 
    Detail: Key (userid)=(0) is not present in table "users". 
    Error Code: 0 
    Call: INSERT INTO address (ID, userid, address) VALUES (?, ?, ?) 
bind => [43, 0, some address] 
    Query: InsertObjectQuery([email protected]) 

的錯誤是非常基本的,並指出該用戶ID值是沒有得到的地址記錄集。好像有足夠的信息讓持久性管理者在這裏完成這個簡單的事務。映射中出了什麼問題?

+0

顯然,持久性管理器不喜歡子表中的外鍵映射到相應的對象。由於這種關係是單向的,它只能從父母到孩子實施導航。因此讓外鍵不暴露在孩子身上將確保沒有方法直接找到和/或直接導航孩子而不是父母。 所以在上面的例子中,所有需要的是刪除 @Column(name =「userid」) private long userId; public long getUserId(){ return userId; } public void setUserId(long userId){this.userId = userId; } – user1796571

+0

好吧,刪除讓我通過插入,但它實際上沒有用。 user_id不會保留在地址表中。所以實際上這是作爲一個空值。 – user1796571

回答

1

地址有你沒有設置的userid。除非要設置從地址到用戶的一對一關係映射,否則需要手動設置爲用戶的ID。使用映射userid字段的連接列設置onetoone,並標記由新關係映射的user-> address。例如http://www.eclipse.org/eclipselink/api/2.0/javax/persistence/OneToOne.html

+0

無法在此上下文中設置UserId。由於尚未分配,因此它總是空的。 – user1796571

+0

要麼保留並刷新用戶以獲取指定的ID,您可以將該ID用於該字段,或者將類型從long更改爲Long,以便可以插入null,直到您可以設置它爲止。但是該字段正在被地址'userid屬性控制,這就是爲什麼你插入0的原因。您需要從地址到用戶的映射,讓提供商爲您設置值。 – Chris

+0

是的,這將工作。但是模型本身是有缺陷的。像這樣的OneToOne關係從未在數據庫級別真正實施。你確實回答了提出的問題,所以我必須給你。 – user1796571

0

我做錯了什麼是定義允許OneToMany但嘗試將它建模爲OneToOne關係的關係。

我應該在用戶表上有一個address_id列,而不是地址表上的user_id。如果我在用戶表中定義address_id列並映射像我這樣的實體

@OneToOne(cascade=CascadeType.PERSIST) 
@JoinColumn(name="address_id") 
//@PrimaryKeyJoinColumn 
private Address address; 

它工作得很好。這是持久性管理器期望定義OneToOne關係的方式。