hibernate ElementCollection查找错误的列

时间:2017-01-08 18:04:16

标签: java hibernate

我正在尝试为大学课程制作一个基本的项目编辑器。我之前从未使用过hibernate所以我遇到了很多问题而且这个问题让我感到难过 - 必须有一些我在文档中不理解的东西。

当我尝试加载项目中的活动列表时,出现此错误:

Hibernate: select activities0_.Project_Id as Project_6_0_0_, activities0_.activities_Id as activiti8_0_0_, activity1_.Id as Id1_0_1_, activity1_.Description as Descript2_0_1_, activity1_.Duration as Duration3_0_1_, activity1_.End_Date as End_Date4_0_1_, activity1_.Name as Name5_0_1_, activity1_.Project_Id as Project_6_0_1_, activity1_.Start_Date as Start_Da7_0_1_ from Activities activities0_ inner join Activities activity1_ on activities0_.activities_Id=activity1_.Id where activities0_.Project_Id=?
18:40:44.775 [qtp94264799-20] WARN  org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1054, SQLState: 42S22
18:40:44.776 [qtp94264799-20] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Unknown column 'activities0_.activities_Id' in 'field list'

导致会话未正确关闭,数据未被检索,整个程序无法正常工作。

涉及的两个课程是:

@Entity
@Table(name = "Projects")
public class Project implements java.io.Serializable{

    private static final long serialVersionUID = 5115375190980452672L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Project_Id")
    private int id; // this should be set once on creation and never touched
                    // again as it identifies the project uniquely
    @Column(name = "Owner_Id")
    private int ownerId;
    @Column(name = "Name")
    private String name;
    @ElementCollection
    @CollectionTable(name="Activities", joinColumns=@JoinColumn(name="Project_Id"))
    @Column(name="Activity")
    private List<Activity> activities;

    public Project(){

    }
    /**
     * Constructor to load existing project
     * @param idToLoad id of the project to load
     */
    public Project(int idToLoad) { 
//      MySqlDriver.loadObjectWithId(this, idToLoad);
        org.hibernate.Session session;
        try{
            session=Start.getFactory().getCurrentSession();
        }catch(Exception e){
            System.out.println("Could not load project.");
            System.out.println("Error while creating mysql session: "+e);
            return;
        }
        try{
            session.beginTransaction();
            session.load(this, idToLoad);
            this.activities.size();
            session.getTransaction().commit();
        }catch(Exception e){
            System.out.println("Could not load project.");
            System.out.println("Error while committing changes: "+e);
            session.getTransaction().commit();
        }
    }

    /**
     * Creates new project
     * @param newName name of the new project
     * @param newId id of the new project
     */
    public Project(String newName, int owner_Id) { // on creation a project
                                                        // only has a name and a
                                                        // unique id
        this.name = newName;
        this.ownerId = owner_Id;
        this.activities = null;
    }

    public void addActivity(String activityName) { // add new activity to the
                                                    // project with given
                                                    // attributes
        Activity newActivity = new Activity(activityName, this.id);
        this.activities.add(newActivity);
    }

    public void setName(String newName) { // change project name
        this.name = newName;
    }

    public String getName() { // return project name
        return this.name;
    }

    public List<Activity> getActivities(){
        return this.activities;
    }

    public int getId(){
        return this.id;
    }

    public void commitChanges() {
        for (Activity act : this.activities)
            act.commitChanges(); // commit changes made to all activities in the
                                    // project
        MySqlDriver.saveObject(this);
    }

    public void deleteProject() {
        MySqlDriver.deleteObject(this);
    }

    public Activity selectActivity(String activityName) {
        for (Activity act : activities) { // cycle through activities and return
                                            // the one with the given name
            if (act.getName().equals(activityName))
                return act;
        }
        return null;
    }

    public void deleteActivity(String deleteMeName) {
        for (Activity act : activities) { // cycle through activities and delete
                                            // the one with the given name
            if (act.getName().equals(deleteMeName)) {
                MySqlDriver.deleteObject(act);
                activities.remove(act);
                break;
            }
        }
    }

    public void grantAccessToProject(String otherUser) {
        // grants permission to view and modify project database to user
        // otherUser
    }
}

@Entity
@Table(name="Activities")
public class Activity {

    private static final long minDateDiff = 3600000;    //1H in milliseconds

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="Id")
    private int id;
    @Column(name="Name")
    private String name;    //using same name for activities in same project not supported.
    @Column(name="Description")
    private String description;
    @Column(name="Start_Date")
    @Temporal(TemporalType.TIMESTAMP)
    private Date startDate;
    @Column(name="End_Date")
    @Temporal(TemporalType.TIMESTAMP)
    private Date endDate;
    @Column(name="Duration")
    private long duration;
    @Column(name="Project_Id")
    private int parent;



    /**
     * Activity constructor, automatically sets default start and end date.
     * @param newName Name of the new activity
     * @param parent id of parent project
     */
    public Activity(String newName, int parent){
        this.parent = parent;
        this.name = newName;
        this.startDate = new Date();    //start date by default is creation time
        this.endDate = new Date();
        this.endDate.setTime(startDate.getTime() + Activity.minDateDiff);   //end date by default is 1 hour ahead of start date
        this.description = new String();
        this.getDateDiff(startDate, endDate, TimeUnit.HOURS);   //set default duration
    }

    public void getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {    //converts difference between dates from 
                                                                                //milliseconds to given time unit
                                                                            //credit to Sebastien Lorber (from StackOverflow)
        long diffInMillies = date2.getTime() - date1.getTime();
        this.duration=timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
    }

    public void setName(String newName){
        this.name = newName;
    }

    public String getName(){
        return this.name;
    }

    public void setStartDate(Date newStartDate){
        Date dummyDate = new Date();
        if(newStartDate.getTime() > dummyDate.getTime()){   //rough check to ensure start date
                                                            //isn't in the past - precise enough
                                                            //for application's needs
             this.startDate = newStartDate; 
        }
        if(this.startDate.getTime() >= this.endDate.getTime()){ //shifts endDate 1 hour ahead of startDate if the new startDate
                                                                //is higher
            this.endDate.setTime(this.startDate.getTime() + 3600000);
        }
    }

    public void setEndDate(Date newEndDate){
        Date dummyDate = new Date();
        if(newEndDate.getTime() > dummyDate.getTime() && this.startDate.getTime() < newEndDate.getTime()){
                                                            //rough check to ensure end date
                                                            //isn't in the past or before start date - precise enough
                                                            //for application's needs
             this.endDate = newEndDate; 
        }
    }

    public void setDescription(String newDescription){
        this.description = newDescription;
    }

    public String getDescription(){
        return this.description;
    }

    public void addManager(String newManager){
        //this.activityManagers.add(newManager);

    }

    /**
     * Returns how long the Activity will take.
     * @return Activity duration in hours.
     */
    public long getDuration(){  //returns how long the activity will take in hours.
        return this.duration;
    }

    /**
     * Saves Activity data to database
     */
    public void commitChanges(){
        MySqlDriver.saveObject(this);
    }

    public void loadData(int activityToLoadId){ //loads data of activity with name activityToLoadName from database
        this.id = activityToLoadId;
        MySqlDriver.loadObjectWithId(this, activityToLoadId);
    }
}

一切都在进行中,所以有些方法是拼凑的,但我认为问题在于我映射ElementCollection的方式。

正如你所看到的,我没有提到专栏#34; activities_Id&#34;它是如此坚定地寻找和试图加载它的代码只不过是session.get()和hibernate.initialize():

for(Integer projId : this.myProjectIds){
    try{
        Session newSession = Start.getFactory().getCurrentSession();
        newSession.beginTransaction();
        Project dummyProject = (Project) newSession.get(Project.class, projId);
        Hibernate.initialize(dummyProject.getActivities());
        this.myProjects.add(dummyProject);
        newSession.getTransaction().commit();
    }catch(Exception e){
        System.out.println(e);
    }
}

提前感谢您提供的任何帮助!

-update- 我按照建议尝试使用OneToMany,但我仍然得到类似的关于我从未提及过的列的抱怨。这就是我现在在Project类中的内容(而不是elementcollection):

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Activity> activities;

这就是我在Activities类中的内容(而不是父id int):

@ManyToOne
private Project parent;

我现在得到的错误更令人困惑:

Hibernate: select activities0_.Project_Project_Id as Project_1_2_0_, activities0_.activities_Id as activiti2_2_0_, activity1_.Id as Id1_0_1_, activity1_.Description as Descript2_0_1_, activity1_.Duration as Duration3_0_1_, activity1_.End_Date as End_Date4_0_1_, activity1_.Name as Name5_0_1_, activity1_.parent_Project_Id as parent_P7_0_1_, activity1_.Start_Date as Start_Da6_0_1_, project2_.Project_Id as Project_1_1_2_, project2_.Name as Name2_1_2_, project2_.Owner_Id as Owner_Id3_1_2_ from Projects_Activities activities0_ inner join Activities activity1_ on activities0_.activities_Id=activity1_.Id left outer join Projects project2_ on activity1_.parent_Project_Id=project2_.Project_Id where activities0_.Project_Project_Id=?
15:54:02.463 [qtp94264799-20] WARN  org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1146, SQLState: 42S02
15:54:02.464 [qtp94264799-20] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Table 'Project32.Projects_Activities' doesn't exist

因为它似乎只是在组成列名。也许我在mysql表中遗漏了一些东西,我在&#34; Project_Id&#34;之间有一个参考。活动中的列和Projects表中具有相同名称的主键。

1 个答案:

答案 0 :(得分:0)

原来我没有正确使用注释,因为我怀疑,要解决我必须在项目和活动中指定@JoinColumn的问题(并使活动可序列化,我最初忘了做)。现在课程如下:     @实体     @table(名称= “活动”)的     public class Activity实现了java.io.Serializable {

    private static final long minDateDiff = 3600000;    //1H in milliseconds

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="Id")
    private int id;
    @Column(name="Name")
    private String name;    //using same name for activities in same project not supported.
    @Column(name="Description")
    private String description;
    @Column(name="Start_Date")
    @Temporal(TemporalType.TIMESTAMP)
    private Date startDate;
    @Column(name="End_Date")
    @Temporal(TemporalType.TIMESTAMP)
    private Date endDate;
    @Column(name="Duration")
    private long duration;
    @ManyToOne
    @JoinColumn(name="Project_Id")
    private Project parent;


    public Activity(){

    }
    /**
     * Activity constructor, automatically sets default start and end date.
     * @param newName Name of the new activity
     * @param parent id of parent project
     */
    public Activity(String newName, int parentId){
        this.parent = new Project(parentId);
        this.name = newName;
        this.startDate = new Date();    //start date by default is creation time
        this.endDate = new Date();
        this.endDate.setTime(startDate.getTime() + Activity.minDateDiff);   //end date by default is 1 hour ahead of start date
        this.description = new String();
        this.getDateDiff(startDate, endDate, TimeUnit.HOURS);   //set default duration
    }

    public void getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {    //converts difference between dates from 
                                                                                //milliseconds to given time unit
                                                                            //credit to Sebastien Lorber (from StackOverflow)
        long diffInMillies = date2.getTime() - date1.getTime();
        this.duration=timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
    }

    public void setName(String newName){
        this.name = newName;
    }

    public String getName(){
        return this.name;
    }

    public void setStartDate(Date newStartDate){
        Date dummyDate = new Date();
        if(newStartDate.getTime() > dummyDate.getTime()){   //rough check to ensure start date
                                                            //isn't in the past - precise enough
                                                            //for application's needs
             this.startDate = newStartDate; 
        }
        if(this.startDate.getTime() >= this.endDate.getTime()){ //shifts endDate 1 hour ahead of startDate if the new startDate
                                                                //is higher
            this.endDate.setTime(this.startDate.getTime() + 3600000);
        }
    }

    public void setEndDate(Date newEndDate){
        Date dummyDate = new Date();
        if(newEndDate.getTime() > dummyDate.getTime() && this.startDate.getTime() < newEndDate.getTime()){
                                                            //rough check to ensure end date
                                                            //isn't in the past or before start date - precise enough
                                                            //for application's needs
             this.endDate = newEndDate; 
        }
    }

    public void setDescription(String newDescription){
        this.description = newDescription;
    }

    public String getDescription(){
        return this.description;
    }

    public void addManager(String newManager){
        //this.activityManagers.add(newManager);

    }

    /**
     * Returns how long the Activity will take.
     * @return Activity duration in hours.
     */
    public long getDuration(){  //returns how long the activity will take in hours.
        return this.duration;
    }

    /**
     * Saves Activity data to database
     */
    public void commitChanges(){
        MySqlDriver.saveObject(this);
    }

    public void loadData(int activityToLoadId){ //loads data of activity with name activityToLoadName from database
        this.id = activityToLoadId;
        MySqlDriver.loadObjectWithId(this, activityToLoadId);
    }
}

@Entity
@Table(name = "Projects")
public class Project implements java.io.Serializable{

    private static final long serialVersionUID = 5115375190980452672L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Project_Id")
    private int id; // this should be set once on creation and never touched
                    // again as it identifies the project uniquely
    @Column(name = "Owner_Id")
    private int ownerId;
    @Column(name = "Name")
    private String name;
//  @ElementCollection
//  @CollectionTable(name="Activities", joinColumns=@JoinColumn(name="Project_Id"))
//  @Column(name="Activity")
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name="Project_Id")
    private List<Activity> activities;

    public Project(){

    }
    /**
     * Constructor to load existing project
     * @param idToLoad id of the project to load
     */
    public Project(int idToLoad) { 
//      MySqlDriver.loadObjectWithId(this, idToLoad);
        org.hibernate.Session session;
        try{
            session=Start.getFactory().getCurrentSession();
        }catch(Exception e){
            System.out.println("Could not load project.");
            System.out.println("Error while creating mysql session: "+e);
            return;
        }
        try{
            session.beginTransaction();
            session.load(this, idToLoad);
            this.activities.size();
            session.getTransaction().commit();
        }catch(Exception e){
            System.out.println("Could not load project.");
            System.out.println("Error while committing changes: "+e);
            session.getTransaction().commit();
        }
    }

    /**
     * Creates new project
     * @param newName name of the new project
     * @param newId id of the new project
     */
    public Project(String newName, int owner_Id) { // on creation a project
                                                        // only has a name and a
                                                        // unique id
        this.name = newName;
        this.ownerId = owner_Id;
        this.activities = null;
    }

    public void addActivity(String activityName) { // add new activity to the
                                                    // project with given
                                                    // attributes
        Activity newActivity = new Activity(activityName, this.id);
        this.activities.add(newActivity);
    }

    public void setName(String newName) { // change project name
        this.name = newName;
    }

    public String getName() { // return project name
        return this.name;
    }

    public List<Activity> getActivities(){
        return this.activities;
    }

    public int getId(){
        return this.id;
    }

    public void commitChanges() {
        for (Activity act : this.activities)
            act.commitChanges(); // commit changes made to all activities in the
                                    // project
        MySqlDriver.saveObject(this);
    }

    public void deleteProject() {
        MySqlDriver.deleteObject(this);
    }

    public Activity selectActivity(String activityName) {
        for (Activity act : activities) { // cycle through activities and return
                                            // the one with the given name
            if (act.getName().equals(activityName))
                return act;
        }
        return null;
    }

    public void deleteActivity(String deleteMeName) {
        for (Activity act : activities) { // cycle through activities and delete
                                            // the one with the given name
            if (act.getName().equals(deleteMeName)) {
                MySqlDriver.deleteObject(act);
                activities.remove(act);
                break;
            }
        }
    }

    public void grantAccessToProject(String otherUser) {
        // grants permission to view and modify project database to user
        // otherUser
    }
}