简体   繁体   English

为什么外键数据将无法持久保存到mysql数据库?

[英]Why will foreign key data will not persist to mysql database?

I am working with a basic mySQL relational database using java. 我正在使用Java使用基本的mySQL关系数据库。 I have attached the entity classes for two tables that have a 1:M relationship. 我已为具有1:M关系的两个表附加了实体类。 I have defined the 1 is to many and many is to 1 relationships in the entity tables. 我已经在实体表中定义了“ 1对很多”关系。 In the Projects class, I wanted to declare the foreign key (private int contractor_id) along with getters and setters (as shown commented out), but I kept getting a compile error stating the following *Multiple writable mappings exist for the field [projects.contractor_id]. 在Projects类中,我想同时声明外键(私有int contractor_id)以及getter和setter(如注释所示),但是我不断收到编译错误,指出以下内容*项目[field.projects.com.cn]存在多个可写映射。 contractor_id。 Only one may be defined as writable, all others must be specified read-only.* I therefore commented them out as their value is set already in the BusinessAccount class. 只能将其中一个定义为可写,所有其他都必须指定为只读。*因此,由于在BusinessAccount类中已经设置了它们的值,因此我将它们注释掉。 The data is now persisting to the database using the 'addProject()' method I have shown. 现在,已使用我显示的“ addProject()”方法将数据持久保存到数据库中。 However, the field contractor_id (ie the foreign key) is being passed as null to the Projects table. 但是,字段contractor_id(即外键)作为null传递给Projects表。 I have a value for contractor_id for the session (named sessionContractorId) but I am unable to pass it to the database as I have no setter for this table. 我有一个用于会话的contractor_id的值(名为sessionContractorId),但由于没有此表的设置程序,因此无法将其传递给数据库。 Any suggestions would be appreciated on how to persist the value for the foreign key to the database? 关于如何将数据库外键的值持久化的任何建议将不胜感激。

@Entity
@Table(name = "business_accounts")
public class BusinessAccount {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@Column(name = "first_name")
private String firstName;

@Column(name = "surname")
private String surname;

@OneToMany(mappedBy = "businessAccount", fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
private List<Projects> projects;



public int getId() {
    return id;
}

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

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getSurname() {
    return surname;
}

public void setSurname(String surname) {
    this.surname = surname;
}

public List<Projects> getProjects()
{
    if (projects == null)
    {
        projects = new ArrayList<Projects>();
    }

    return projects;
}

public void setProjects(List<Projects> projects)
{
    this.projects = projects;
}

}



@Entity
@Table(name = "projects")
public class Projects {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int project_id;

@Column(name = "project_name")
private String projectName;

@Column(name = "project_description")
private String projectDescription;

//@Column(name = "contractor_id")
//private int contractorId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({ @JoinColumn(name = "contractor_id", referencedColumnName="id") })
private BusinessAccount businessAccount;


public BusinessAccount getBusinessAccount() {
    if (businessAccount == null) {
        businessAccount = new BusinessAccount();
    }
    return businessAccount;
}

public void setBusinessAccount(BusinessAccount businessAccount) {
    this.businessAccount = businessAccount;
}

public int getProject_id() {
    return project_id;
}

public void setProject_id(int project_id) {
    this.project_id = project_id;
}

public String getProjectName() {
    return projectName;
}

public void setProjectName(String projectName) {
    this.projectName = projectName;
}

public String getProjectDescription() {
    return projectDescription;
}

public void setProjectDescription(String projectDescription) {
    this.projectDescription = projectDescription;
}

//public int getContractorId() {
    //return contractorId;
//}

//public void setContractorId(int contractorId) {
    //this.contractorId = contractorId;
//}

}



@ManagedBean
@ViewScoped
public class ProjectBean implements Serializable {

private static final long serialVersionUID = -2107387060867715013L;
private static final String PERSISTENCE_UNIT_NAME = "NeedABuilderUnit";
private static EntityManagerFactory factory;

private Projects projects;


private List<BusinessAccount> businessAccount;

public ProjectBean() {
    factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    EntityManager em = factory.createEntityManager();

    List<BusinessAccount> businessAccount = em.createQuery("from BusinessAccount a", BusinessAccount.class)
            .getResultList();
    em.close();
    setBusinessAccount(businessAccount);
}

@PostConstruct
public void init() {
    projects = new Projects();
}

public String addProject() {
    factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    EntityManager em = factory.createEntityManager();   
        em.getTransaction().begin();

        String sessionEmail=Util.getEmail();
        Query myQuery = em.createQuery("SELECT u FROM BusinessAccount u WHERE u.email=:email");
        myQuery.setParameter("email", sessionEmail);
        List<BusinessAccount> accounts=myQuery.getResultList();
        int sessionContractorId=accounts.get(0).getId();
        em.persist(projects);
        em.getTransaction().commit();
        em.close();

        return "success";
    }

There are two things I notice about the code. 我注意到有关代码的两件事。

First, the code should work with entities and ignore the id fields for the particular entities. 首先,代码应使用实体,并忽略特定实体的id字段。 So when you fetch the account, it should grab the entity instead of the id: 因此,当您提取帐户时,它应该获取实体而不是ID:

//Don't do this
List<BusinessAccount> accounts=myQuery.getResultList();
int sessionContractorId=accounts.get(0).getId();

//Instead do this
List<BusinessAccount> accounts=myQuery.getResultList();
BusinessAccount account =accounts.get(0); //hopefully an account exists

Second, in JPA you are responsible for managing both sides of an association. 其次,在JPA中,您负责管理关联双方。 So you must add the Account to the Project and on the other side of the relationship set the Project for the Account . 因此,您必须将Account添加到Project并在关系的另一侧为Account设置Project I never see this occur in the code, I only see the projects (not sure of its origin) being persisted. 我从没在代码中看到这种情况,仅看到持久化的projects (不确定其来源)。 Assuming projects is a List<Project> it would look something like this: 假设projects是一个List<Project> ,它将看起来像这样:

public String addProject() {
        factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        EntityManager em = factory.createEntityManager();   
        em.getTransaction().begin();

        String sessionEmail=Util.getEmail();
        Query myQuery = em.createQuery("SELECT u FROM BusinessAccount u WHERE u.email=:email");
        myQuery.setParameter("email", sessionEmail);
        List<BusinessAccount> accounts=myQuery.getResultList();
        BusinessAccount account =accounts.get(0);

        projects.setBusinessAccount(account); //managing both sides
        account.getProjects().add(projects); //managing both sides
        em.persist(projects);
        em.getTransaction().commit();
        em.close();

        return "success";
    }

On a side note, you may want to change the class name to Project and use the variable name project since it more accurately depicts the relationship. 附带说明一下,您可能希望将类名更改为Project并使用变量名project因为它可以更准确地描述关系。 Also since you are creating a new Project you will need to instantiate the List<BusinessAccount> : 同样,由于您正在创建一个新Project您将需要实例化List<BusinessAccount>

List<BusinessAccount> projects = new ArrayList<BusinessAccount>();

Hopefully this will solve your issues, I would recommend watching a this video tutorial I created on Bidirectional One To Many Relationships. 希望这能解决您的问题,我建议您观看我在双向一对多关系上创建的此视频教程

You should use @JoinColumn(name="id_user", insertable = false, updatable = false) 您应该使用@JoinColumn(name="id_user", insertable = false, updatable = false)

Please refer: Multiple writable mappings in JPA? 请参考: JPA中的多个可写映射?

Hope this helps :) 希望这可以帮助 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM