2010-09-03 27 views
2

在Netbeans中設置Java持久性時出現錯誤。我使用MySQL作爲後端數據庫服務器。使用Netbeans的Java Persistence API中的外鍵問題6.9.1

我的代碼如下,

數據庫

CREATE TABLE `hub` (
`hub_ID` INT(11) NOT NULL AUTO_INCREMENT, 
`hub_Name` VARCHAR(45) NOT NULL, 
PRIMARY KEY (`hub_ID`), 
UNIQUE INDEX `hub_Name` (`hub_Name`) 
)ENGINE=MyISAM 

CREATE TABLE `company` (
`company_ID` INT(11) NOT NULL AUTO_INCREMENT, 
`company_Name` VARCHAR(45) NOT NULL, 
`company_hub_ID` INT(11) NOT NULL, 
PRIMARY KEY (`company_ID`), 
INDEX `fk_company_hub1` (`company_hub_ID`) 
) 

的persistence.xml

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="testJPAPU" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
    <class>testjpa.Hub</class> 
    <class>testjpa.Company</class> 
    <properties> 
     <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/logistikumdispatch"/> 
     <property name="javax.persistence.jdbc.password" value="rootroot"/> 
     <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> 
     <property name="javax.persistence.jdbc.user" value="root"/> 
    </properties> 
    </persistence-unit> 
</persistence> 

Hub.java(實體類的項目)

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 

package testjpa; 

import java.io.Serializable; 
import java.util.Collection; 
import javax.persistence.Basic; 
import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.NamedQueries; 
import javax.persistence.NamedQuery; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 

/** 
* 
* @author Anjum 
*/ 
@Entity 
@Table(name = "hub") 
@NamedQueries({ 
    @NamedQuery(name = "Hub.findAll", query = "SELECT h FROM Hub h"), 
    @NamedQuery(name = "Hub.findByHubID", query = "SELECT h FROM Hub h WHERE h.hubID = :hubID"), 
    @NamedQuery(name = "Hub.findByHubName", query = "SELECT h FROM Hub h WHERE h.hubName = :hubName")}) 
public class Hub implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "hub_ID") 
    private Integer hubID; 
    @Basic(optional = false) 
    @Column(name = "hub_Name") 
    private String hubName; 

    @OneToMany(mappedBy="hub", cascade=CascadeType.ALL) 
    @JoinColumn(name="company_hub_ID") 
    private Collection<Company> companies; 

    public Hub() { 
    } 

    public Hub(Integer hubID) { 
     this.hubID = hubID; 
    } 

    public Hub(Integer hubID, String hubName) { 
     this.hubID = hubID; 
     this.hubName = hubName; 
    } 

    public Integer getHubID() { 
     return hubID; 
    } 

    public void setHubID(Integer hubID) { 
     this.hubID = hubID; 
    } 

    public String getHubName() { 
     return hubName; 
    } 

    public void setHubName(String hubName) { 
     this.hubName = hubName; 
    } 

    public Collection<Company> getCompanies() 
    { 
     return companies; 
    } 

    public void setCompanies(Collection<Company> companies) 
    { 
     this.companies = companies; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (hubID != null ? hubID.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Hub)) { 
      return false; 
     } 
     Hub other = (Hub) object; 
     if ((this.hubID == null && other.hubID != null) || (this.hubID != null && !this.hubID.equals(other.hubID))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "testjpa.Hub[hubID=" + hubID + "]"; 
    } 

} 

Company.java(實體類在Project)

package testjpa; 

import java.io.Serializable; 
import javax.persistence.Basic; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.NamedQueries; 
import javax.persistence.NamedQuery; 
import javax.persistence.Table; 

/** 
* 
* @author Anjum 
*/ 
@Entity 
@Table(name = "company") 
@NamedQueries({ 
    @NamedQuery(name = "Company.findAll", query = "SELECT c FROM Company c"), 
    @NamedQuery(name = "Company.findByCompanyID", query = "SELECT c FROM Company c WHERE c.companyID = :companyID"), 
    @NamedQuery(name = "Company.findByCompanyName", query = "SELECT c FROM Company c WHERE c.companyName = :companyName"), 
    @NamedQuery(name = "Company.findByCompanyhubID", query = "SELECT c FROM Company c WHERE c.companyhubID = :companyhubID")}) 
public class Company implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "company_ID") 
    private Integer companyID; 
    @Basic(optional = false) 
    @Column(name = "company_Name") 
    private String companyName; 
    @Basic(optional = false) 
    @Column(name = "company_hub_ID") 
    private int companyhubID; 
    @ManyToOne() 
    @JoinColumn(name="hub_ID", insertable=false, updatable=false) 
    private Hub hub; 
    public Company() { 
    } 

    public Company(Integer companyID) { 
     this.companyID = companyID; 
    } 

    public Company(Integer companyID, String companyName, int companyhubID) { 
     this.companyID = companyID; 
     this.companyName = companyName; 
     this.companyhubID = companyhubID; 
    } 

    public Integer getCompanyID() { 
     return companyID; 
    } 

    public void setCompanyID(Integer companyID) { 
     this.companyID = companyID; 
    } 

    public String getCompanyName() { 
     return companyName; 
    } 

    public void setCompanyName(String companyName) { 
     this.companyName = companyName; 
    } 

    public int getCompanyhubID() { 
     return companyhubID; 
    } 

    public void setCompanyhubID(int companyhubID) { 
     this.companyhubID = companyhubID; 
    } 

    public Hub getHub() 
    { 
     return hub; 
    } 

    public void setHub(Hub hub) 
    { 
     this.hub = hub; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (companyID != null ? companyID.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Company)) { 
      return false; 
     } 
     Company other = (Company) object; 
     if ((this.companyID == null && other.companyID != null) || (this.companyID != null && !this.companyID.equals(other.companyID))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "testjpa.Company[companyID=" + companyID + "]"; 
    } 

} 

主程序

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package testjpa; 

import javax.persistence.EntityManager; 
import javax.persistence.EntityManagerFactory; 
import javax.persistence.Persistence; 

/** 
* 
* @author Anjum 
*/ 
public class Main { 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     EntityManagerFactory emf = Persistence.createEntityManagerFactory("testJPAPU"); 
     EntityManager em = emf.createEntityManager(); 

     em.getTransaction().begin(); 

     Company c1 = new Company(); 
     c1.setCompanyName("ays"); 


     Hub h1 = new Hub(); 
     h1.setHubName("abc"); 
     em.persist(h1); 
     c1.setHub(h1); 

     em.persist(c1); 
     em.flush(); 

    } 
} 

輸出

[EL Info]: 2010-09-03 14:39:02.639--ServerSession(3199106)--EclipseLink, version: Eclipse Persistence Services - 2.0.2.v20100323-r6872 
[EL Info]: 2010-09-03 14:39:03.371--ServerSession(3199106)--file:/C:/Users/Anjum/Documents/NetBeansProjects/testJPA/build/classes/_testJPAPU login successful 

問題

我的問題是,外鍵company.company_hub_ID在數據庫comapany.company_name = 「AYS」 更新。但是company.company_hub_ID中總是有0。

Hub也正確更新。意味着沒有連接或JPA問題。問題只存在於關係中。

在此先感謝您的幫助。

回答

0

某些東西在您的映射和數據庫模式之間沒有對齊。數據庫模式是由JPA提供者生成的嗎?

該映射在公司類中定義了hub_id加入列,但數據庫模式缺少該列(它具有「company_hub_ID」)。

嘗試以下操作:

從@OneToMany的側面卸下@JoinColumn。 @ OneToMany + @ JoinColumn僅用於映射外鍵上的單向onetomany關聯(不包含連接表)。您的關聯是一個雙向onetomany,因此@OneToMany在反面有mappedBy,在擁有一面有@ManyToOne + @JoinColumn(可選)。不要將可插入/可更新設置爲false。

+0

感謝您的回覆romanb。 我收到您的建議的錯誤。 異常描述:多個可寫映射領域[company.company_hub_ID]存在。只有一個可以被定義爲可寫,所有其他都必須被指定爲只讀。 映射:org.eclipse.persistence.mappings.OneToOneMapping [hub] 描述符:RelationalDescriptor(testjpa.Company - > [DatabaseTable(company)]) – 2010-09-03 10:12:26

+0

是的,由JPA provider生成的數據庫模式.. – 2010-09-03 10:19:43

0

我同意羅曼布的建議。

由於該關聯是雙向的,因此請確保您設置了「post」中指出的「鏈接的兩側」。

試着改變你這樣的代碼:

public class Hub { 
    ... 
    @OneToMany(mappedBy="hub", cascade=CascadeType.ALL) 
    private Collection<Company> companies = new ArrayList<Company>(); 

    ... 
    public void addCompany(Company company) { 
     company.setHub(this); 
     this.companies.add(company); 
    }  
    ... 
} 

public class Company { 
    ...   
    @ManyToOne 
    @JoinColumn(name="company_hub_ID") 
    private Hub hub;  
    ... 
} 

public class Main { 

    public static void Main(String[] args) { 
     ... 
     Company c1 = new Company(); 
     c1.setCompanyName("ays"); 

     Hub h1 = new Hub(); 
     h1.setHubName("abc"); 
     h1.addCompany(c1); 
     em.persist(h1); 
    } 

} 

此外,使用其他的ID生成策略比GenerationType.IDENTITY,作爲標識符是無法訪問,直到發生在插入之後。

1

如前所述,您不應在OneToMany/ManyToOne關聯的兩側使用JoinColumn,而只能在自己身邊(多方面)使用。將其從OneToMany一面刪除並修復列名稱。

你也不應該在Company實體中擁有companyhubID屬性來保存外鍵(實際上這些東西應該隱藏在對象級別)。從JoinColumn中刪除屬性和insertable=false, updatable=false

所以映射應該是:

@Entity 
... 
public class Hub implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "hub_ID") 
    private Integer hubID; 
    @Basic(optional = false) 
    @Column(name = "hub_Name") 
    private String hubName; 

    @OneToMany(mappedBy="hub", cascade=CascadeType.ALL) // @JoinColumn(name="company_hub_ID") // THIS IS WRONG private Collection companies = new HashSet() 
    ... 
    // method to set both sides of the link of the bidirectional association 
    public void addToCompanies(Company company) { 
     company.setHub(this); 
     this.companies.add(company); 
    } 
}

而且

@Entity 
... 
public class Company implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "company_ID") 
    private Integer companyID; 
    @Basic(optional = false) 
    @Column(name = "company_Name") 
    private String companyName; 
// @Basic(optional = false) // @Column(name = "company_hub_ID") // private int companyhubID; // NO, DON'T @ManyToOne() @JoinColumn(name="company_hub_ID"/*, insertable=false, updatable=false*/) private Hub hub; 
    ... 
}

一些補充說明:

  • 使用IDENTITY策略ID生成的罰款。
  • 您應該使用InnoDB表進行參照完整性。

另請注意,您的演示代碼不正確,您沒有適當地設置關聯。它應該是:

Company c1 = new Company(); 
c1.setCompanyName("ays"); 
Hub h1 = new Hub(); 
h1.setHubName("abc"); 
h1.addToCompanies.add(c1); // set the bidirectional association 

em.persist(h1);    // JPA will cascade the persist 
em.flush(); 
0

最後我用羅曼B的支持解決了這個問題。

謝謝你的幫助 「ROMANB」。

看看下面我怎麼解決了,你可以使用這種技術來實現持久性與在NetBeans外鍵。

public class Company implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "company_ID", nullable=true) 
    private Integer companyID; 
    @Basic(optional = false) 
    @Column(name = "company_Name") 
    private String companyName; 
    @Basic(optional = false) 
    @Column(name = "company_hub_ID", nullable=false, updatable=false, insertable=false) 
    private int companyhubID; 
    @ManyToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name="company_hub_ID") 
    private Hub hub_ref; 
.......... 
.......... 

public class Hub implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "hub_ID") 
    private Integer hubID; 
    @Basic(optional = false) 
    @Column(name = "hub_Name") 
    private String hubName; 

    @OneToMany(mappedBy="hub_ref", cascade=CascadeType.ALL) 
    private Collection<Company> companies; 

    ................ 
    ................ 
    \\ in Hub class 
public void addCompany(Company company) 
    { 
     if(this.companies == null) 
     { 
      this.companies = new ArrayList<Company>(); 
     } 
     this.companies.add(company); 
     company.setHub(this); 
    } 

最後的主類

public static void main(String[] args) { 
     EntityManagerFactory emf = Persistence.createEntityManagerFactory("testJPAPU"); 
     EntityManager em = emf.createEntityManager(); 



     Company c1 = new Company(); 
     c1.setCompanyName("ays"); 

     Hub h1 = new Hub(); 
     h1.setHubName("abc"); 

     em.getTransaction().begin(); 

     h1.addCompany(c1); 
     em.persist(h1); 

     em.flush(); 

    } 

使用Eclipse 2.0的鏈接來獲得JPA 2.0支持。再次

感謝,並感謝堆棧溢出。

Anjum Shrimali。

+1

不,你不應該有'private int companyhubID;'屬性來表示FK,就像我在回答中寫的那樣。 JPA的重點在於抽象說明,數據庫內容不應該在對象模型中泄漏。所以不,你不應該使用這個「技術來實現NetBeans中外鍵的持久性」。 – 2010-09-04 05:44:15