好久就想玩一下hibernate注解了(因為不用hbm文件,維護起來也簡單,靈活性較高,適應需求變化作出快速變動,還有一些好處就不一一例舉啦),但是沒有時間,今天搞了一下,碰個幾個問題,我想這應該也就新手最容易碰的。問題有三:
第一、Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'systheache0_.theacherId' in 'field list'
第二、Caused by: org.hibernate.MappingException: Could not determine type for: java.util.List, at table: SYS_COURSE, for columns: [org.hibernate.mapping.Column(theacher)]
第三、Caused by: org.hibernate.AnnotationException: property from @OrderBy clause not found: com.itdcl.agcds.webinfo.model.SysCourse.theacherId
問題都列出來啦,那我就進入下一步,解決問題。
第一個問題造成的原因是:異常說明不存在這個column啦,但是查看了一下表,有這個字段啊。為啥報這個異常呢,叫人心煩。別急,看是不是column沒有寫啊。參考一下column屬性:
可選
@Column描述了數據庫表中該字段的詳細定義,這對于根據JPA注解生成數據庫表結構的工具非常有作用.
name:表示數據庫表中該字段的名稱,默認情形屬性名稱一致
nullable:表示該字段是否允許為null,默認為true
unique:表示該字段是否是唯一標識,默認為false
length:表示該字段的大小,僅對String類型的字段有效
insertable:表示在ORM框架執行插入操作時,該字段是否應出現INSETRT語句中,默認為true
updateable:表示在ORM框架執行更新操作時,該字段是否應該出現在UPDATE語句中,默認為true.對于一經創建就不可以更改的字段,該屬性非常有用,如對于birthday字段.
columnDefinition:表示該字段在數據庫中的實際類型.通常ORM框架可以根據屬性類型自動判斷數據庫中字段的類型,但是對于Date類型仍無法確定數據庫中字段類型究竟是DATE,TIME還是TIMESTAMP.此外,String的默認映射類型為VARCHAR,如果要將String類型映射到特定數據庫的BLOB或TEXT字段類型,該屬性非常有用.
看完還是云里霧里吧,我這個問題造成的原因是:表字段是THEACHER_ID,但是pojo類里面是theacherId,本來想偷懶,結果搞得懶沒偷成,反而多花時間啦,記得以后還是加上好。如果是這樣:表字段THEACHERID,pojo類中是theacherId,這個肯定沒有問題啦,不過我以后還是寫上好^_^
接下來繼續解決第二個問題:怎么又與集合打交道啦,哎搞個東西真是一波三折啊。那就從集合上找問題啦。到關網論壇一查,原來是這個東西放錯地啦,但是一般情況下這樣做也不會報錯,既然有問題就改下嘍:
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE },targetEntity=com.itdcl.agcds.webinfo.model.SysCourse.class)
@JoinTable(name = "SYS_THEACHER_COURSE", joinColumns = { @JoinColumn(name = "THEACHER_ID") }, inverseJoinColumns = { @JoinColumn(name = "COURSE_ID") })
@Fetch(FetchMode.SUBSELECT)
@OrderBy("theacherId")
public List<SysCourse> getCourse() {
return course;
}
改成下面這樣就沒事噠:
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE },targetEntity=com.itdcl.agcds.webinfo.model.SysCourse.class)
@JoinTable(name = "SYS_THEACHER_COURSE", joinColumns = { @JoinColumn(name = "THEACHER_ID") }, inverseJoinColumns = { @JoinColumn(name = "COURSE_ID") })
@Fetch(FetchMode.SUBSELECT)
@OrderBy("theacherId")
private List<SysCourse> course = new ArrayList<SysCourse>();
好啦,咱樣就溫習一下注解中關聯關系相關知識:
1) @ManyToOne(fetch=FetchType,cascade=CascadeType)
可選
@ManyToOne表示一個多對一的映射,該注解標注的屬性通常是數據庫表的外鍵
optional:是否允許該字段為null,該屬性應該根據數據庫表的外鍵約束來確定,默認為true
fetch:表示抓取策略,默認為FetchType.EAGER
cascade:表示默認的級聯操作策略,可以指定為ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干組合,默認為無級聯操作
targetEntity:表示該屬性關聯的實體類型.該屬性通常不必指定,ORM框架根據屬性類型自動判斷targetEntity.
示例:
//訂單Order和用戶User是一個ManyToOne的關系
//在Order類中定義
@ManyToOne()
@JoinColumn(name="USER")
public User getUser() {
return user;
}
2)@JoinColumn
可選
@JoinColumn和@Column類似,介量描述的不是一個簡單字段,而一一個關聯字段,例如.描述一個@ManyToOne的字段.
name:該字段的名稱.由于@JoinColumn描述的是一個關聯字段,如ManyToOne,則默認的名稱由其關聯的實體決定.
例如,實體Order有一個user屬性來關聯實體User,則Order的user屬性為一個外鍵,
其默認的名稱為實體User的名稱+下劃線+實體User的主鍵名稱
示例:見@ManyToOne
3)@OneToMany(fetch=FetchType,cascade=CascadeType)
可選
@OneToMany描述一個一對多的關聯,該屬性應該為集體類型,在數據庫中并沒有實際字段.
fetch:表示抓取策略,默認為FetchType.LAZY,因為關聯的多個對象通常不必從數據庫預先讀取到內存
cascade:表示級聯操作策略,對于OneToMany類型的關聯非常重要,通常該實體更新或刪除時,其關聯的實體也應當被更新刪除
例如:實體User和Order是OneToMany的關系,則實體User被刪除時,其關聯的實體Order也應該被全部刪除
示例:
@OneTyMany(cascade=ALL)
public List getOrders() {
return orders;
}
4)@OneToOne(fetch=FetchType,cascade=CascadeType)
可選
@OneToOne描述一個一對一的關聯
fetch:表示抓取策略,默認為FetchType.LAZY
cascade:表示級聯操作策略
示例:
@OneToOne(fetch=FetchType.LAZY)
public Blog getBlog() {
return blog;
}
5)@ManyToMany
可選
@ManyToMany 描述一個多對多的關聯.多對多關聯上是兩個一對多關聯,但是在ManyToMany描述中,中間表是由ORM框架自動處理
targetEntity:表示多對多關聯的另一個實體類的全名,例如:package.Book.class
mappedBy:表示多對多關聯的另一個實體類的對應集合屬性名稱
示例:
User實體表示用戶,Book實體表示書籍,為了描述用戶收藏的書籍,可以在User和Book之間建立ManyToMany關聯
@Entity
public class User {
private List books;
@ManyToMany(targetEntity=package.Book.class)
public List getBooks() {
return books;
}
public void setBooks(List books) {
this.books=books;
}
}
@Entity
public class Book {
private List users;
@ManyToMany(targetEntity=package.Users.class, mappedBy="books")