好久就想玩一下hibernate注解了(因?yàn)椴挥胔bm文件,維護(hù)起來也簡單,靈活性較高,適應(yīng)需求變化作出快速變動(dòng),還有一些好處就不一一例舉啦),但是沒有時(shí)間,今天搞了一下,碰個(gè)幾個(gè)問題,我想這應(yīng)該也就新手最容易碰的。問題有三:
第一、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
問題都列出來啦,那我就進(jìn)入下一步,解決問題。
第一個(gè)問題造成的原因是:異常說明不存在這個(gè)column啦,但是查看了一下表,有這個(gè)字段啊。為啥報(bào)這個(gè)異常呢,叫人心煩。別急,看是不是column沒有寫啊。參考一下column屬性:
可選
@Column描述了數(shù)據(jù)庫表中該字段的詳細(xì)定義,這對于根據(jù)JPA注解生成數(shù)據(jù)庫表結(jié)構(gòu)的工具非常有作用.
name:表示數(shù)據(jù)庫表中該字段的名稱,默認(rèn)情形屬性名稱一致
nullable:表示該字段是否允許為null,默認(rèn)為true
unique:表示該字段是否是唯一標(biāo)識(shí),默認(rèn)為false
length:表示該字段的大小,僅對String類型的字段有效
insertable:表示在ORM框架執(zhí)行插入操作時(shí),該字段是否應(yīng)出現(xiàn)INSETRT語句中,默認(rèn)為true
updateable:表示在ORM框架執(zhí)行更新操作時(shí),該字段是否應(yīng)該出現(xiàn)在UPDATE語句中,默認(rèn)為true.對于一經(jīng)創(chuàng)建就不可以更改的字段,該屬性非常有用,如對于birthday字段.
columnDefinition:表示該字段在數(shù)據(jù)庫中的實(shí)際類型.通常ORM框架可以根據(jù)屬性類型自動(dòng)判斷數(shù)據(jù)庫中字段的類型,但是對于Date類型仍無法確定數(shù)據(jù)庫中字段類型究竟是DATE,TIME還是TIMESTAMP.此外,String的默認(rèn)映射類型為VARCHAR,如果要將String類型映射到特定數(shù)據(jù)庫的BLOB或TEXT字段類型,該屬性非常有用.
看完還是云里霧里吧,我這個(gè)問題造成的原因是:表字段是THEACHER_ID,但是pojo類里面是theacherId,本來想偷懶,結(jié)果搞得懶沒偷成,反而多花時(shí)間啦,記得以后還是加上好。如果是這樣:表字段THEACHERID,pojo類中是theacherId,這個(gè)肯定沒有問題啦,不過我以后還是寫上好^_^
接下來繼續(xù)解決第二個(gè)問題:怎么又與集合打交道啦,哎搞個(gè)東西真是一波三折啊。那就從集合上找問題啦。到關(guān)網(wǎng)論壇一查,原來是這個(gè)東西放錯(cuò)地啦,但是一般情況下這樣做也不會(huì)報(bào)錯(cuò),既然有問題就改下嘍:
@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>();
好啦,咱樣就溫習(xí)一下注解中關(guān)聯(lián)關(guān)系相關(guān)知識(shí):
1) @ManyToOne(fetch=FetchType,cascade=CascadeType)
可選
@ManyToOne表示一個(gè)多對一的映射,該注解標(biāo)注的屬性通常是數(shù)據(jù)庫表的外鍵
optional:是否允許該字段為null,該屬性應(yīng)該根據(jù)數(shù)據(jù)庫表的外鍵約束來確定,默認(rèn)為true
fetch:表示抓取策略,默認(rèn)為FetchType.EAGER
cascade:表示默認(rèn)的級(jí)聯(lián)操作策略,可以指定為ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干組合,默認(rèn)為無級(jí)聯(lián)操作
targetEntity:表示該屬性關(guān)聯(lián)的實(shí)體類型.該屬性通常不必指定,ORM框架根據(jù)屬性類型自動(dòng)判斷targetEntity.
示例:
//訂單Order和用戶User是一個(gè)ManyToOne的關(guān)系
//在Order類中定義
@ManyToOne()
@JoinColumn(name="USER")
public User getUser() {
return user;
}
2)@JoinColumn
可選
@JoinColumn和@Column類似,介量描述的不是一個(gè)簡單字段,而一一個(gè)關(guān)聯(lián)字段,例如.描述一個(gè)@ManyToOne的字段.
name:該字段的名稱.由于@JoinColumn描述的是一個(gè)關(guān)聯(lián)字段,如ManyToOne,則默認(rèn)的名稱由其關(guān)聯(lián)的實(shí)體決定.
例如,實(shí)體Order有一個(gè)user屬性來關(guān)聯(lián)實(shí)體User,則Order的user屬性為一個(gè)外鍵,
其默認(rèn)的名稱為實(shí)體User的名稱+下劃線+實(shí)體User的主鍵名稱
示例:見@ManyToOne
3)@OneToMany(fetch=FetchType,cascade=CascadeType)
可選
@OneToMany描述一個(gè)一對多的關(guān)聯(lián),該屬性應(yīng)該為集體類型,在數(shù)據(jù)庫中并沒有實(shí)際字段.
fetch:表示抓取策略,默認(rèn)為FetchType.LAZY,因?yàn)殛P(guān)聯(lián)的多個(gè)對象通常不必從數(shù)據(jù)庫預(yù)先讀取到內(nèi)存
cascade:表示級(jí)聯(lián)操作策略,對于OneToMany類型的關(guān)聯(lián)非常重要,通常該實(shí)體更新或刪除時(shí),其關(guān)聯(lián)的實(shí)體也應(yīng)當(dāng)被更新刪除
例如:實(shí)體User和Order是OneToMany的關(guān)系,則實(shí)體User被刪除時(shí),其關(guān)聯(lián)的實(shí)體Order也應(yīng)該被全部刪除
示例:
@OneTyMany(cascade=ALL)
public List getOrders() {
return orders;
}
4)@OneToOne(fetch=FetchType,cascade=CascadeType)
可選
@OneToOne描述一個(gè)一對一的關(guān)聯(lián)
fetch:表示抓取策略,默認(rèn)為FetchType.LAZY
cascade:表示級(jí)聯(lián)操作策略
示例:
@OneToOne(fetch=FetchType.LAZY)
public Blog getBlog() {
return blog;
}
5)@ManyToMany
可選
@ManyToMany 描述一個(gè)多對多的關(guān)聯(lián).多對多關(guān)聯(lián)上是兩個(gè)一對多關(guān)聯(lián),但是在ManyToMany描述中,中間表是由ORM框架自動(dòng)處理
targetEntity:表示多對多關(guān)聯(lián)的另一個(gè)實(shí)體類的全名,例如:package.Book.class
mappedBy:表示多對多關(guān)聯(lián)的另一個(gè)實(shí)體類的對應(yīng)集合屬性名稱
示例:
User實(shí)體表示用戶,Book實(shí)體表示書籍,為了描述用戶收藏的書籍,可以在User和Book之間建立ManyToMany關(guān)聯(lián)
@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")