为什么外键数据不会持久存在mysql数据库?

时间:2014-03-13 00:33:38

标签: java mysql jpa-2.0

我正在使用java使用基本的mySQL关系数据库。我已经为两个具有1:M关系的表附加了实体类。我已经定义了1对很多很多是实体表中的1个关系。在Projects类中,我想声明外键(private int contractor_id)以及getter和setter(如注释所示),但我一直收到编译错误,说明以下*字段[项目的存在多个可写映射。 contractor_id。只有一个可以被定义为可写,所有其他的必须被指定为只读。*因此我将它们注释掉,因为它们的值已经在BusinessAccount类中设置。现在,数据使用我已经显示的'addProject()'方法持久保存到数据库。但是,字段contractor_id(即外键)作为null传递给Projects表。我有一个会话的contractor_id值(名为sessionContractorId)但我无法将其传递给数据库,因为我没有此表的setter。有关如何将外键的值保存到数据库的任何建议都会受到赞赏吗?

@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";
    }

2 个答案:

答案 0 :(得分:1)

我注意到代码有两件事。

首先,代码应该与实体一起使用,并忽略特定实体的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

其次,在JPA中,您负责管理协会的双方。因此,您必须将Account添加到Project,并在关系的另一侧设置Project Account。我从未在代码中看到过这种情况,我只看到projects(不确定其来源)是否持久存在。假设projectsList<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";
    }

在旁注中,您可能希望将班级名称更改为Project并使用变量名称project,因为它可以更准确地描述关系。此外,由于您要创建新的Project,因此需要实例化List<BusinessAccount>

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

希望这会解决您的问题,我建议您观看我在双向一对多关系中创建的video tutorial

答案 1 :(得分:0)

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

请参阅:Multiple writable mappings in JPA?

希望这会有所帮助:)