我正在尝试为大学课程制作一个基本的项目编辑器。我之前从未使用过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表中具有相同名称的主键。
答案 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
}
}