java - Netbeans 6.9.1 的 Java Persistence API 中的外键问题

标签 java orm jpa persistence foreign-keys

我在 Netbeans 中设置 Java 持久性时出错。我使用 MySQL 作为后端数据库服务器。

我的代码如下,

数据库

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(项目中的实体类)

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 问题。问题仅出在关系中。

在此先感谢您对我的帮助。

最佳答案

如前所述,您不应在 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;

    <b>@OneToMany(mappedBy="hub", cascade=CascadeType.ALL)
//    @JoinColumn(name="company_hub_ID") // THIS IS WRONG
    private Collection companies = new HashSet()</b>
    ...
    // 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;
<b>//    @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;</b>
    ...
}

一些补充说明:

  • 使用 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();

关于java - Netbeans 6.9.1 的 Java Persistence API 中的外键问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3634468/

相关文章:

python - Django 的 ORM 如何在访问外部对象时设法获取它们

magento - 需要 Magento 模型的文档 (Mage::getModel())

java - 当我有 PIVOT 时,使用 JPA 如何在 native 查询中设置参数

java - Log4j 日志记录不工作

java - 使用流过滤 List<Map<String, String>>

java - 如何协调 getter 和 setter 中最佳的面向对象编程实践与 ORM 框架的需求?

java - Hibernate缓存问题?

java - JPA中三个实体之间的一对多映射

java - 在 C++ 和 Java 之间传播 Oracle 事务

java - Stripe : card holder name verification