JPA的注解
1.@MappedSuperclass
1)@MappedSuperclass注解只能標(biāo)準(zhǔn)在類上:
@Target({java.lang.annotation.ElementType.TYPE})
- 標(biāo)注為@MappedSuperclass的類將不是一個完整的實體類,他將不會映射到數(shù)據(jù)庫表,但是他的屬性都將映射到其子類的數(shù)據(jù)庫字段中。
- 標(biāo)注為@MappedSuperclass的類不能再標(biāo)注@Entity或@Table注解,也無需實現(xiàn)序列化接口。
但是如果一個標(biāo)注為@MappedSuperclass的類繼承了另外一個實體類或者另外一個同樣標(biāo)注了@MappedSuperclass的類的話,他將可以使用@AttributeOverride或@AttributeOverrides注解重定義其父類(無論是否是實體類)的屬性映射到數(shù)據(jù)庫表中的字段。
比如可以重定義字段名或長度等屬性,使用@AttributeOverride中的子屬性@Column進(jìn)行具體的定義。
注意:對于其父類中標(biāo)注@Lob注解的屬性將不能重載,并且@AttributeOverride里的@Column設(shè)置都將不起作用。
JPA規(guī)范中對@Lob注解并沒有說明不能同時標(biāo)注@Column注解,但是在實際使用中Hibernate JPA不支持這中標(biāo)注方式。
- 此外,這樣的類還可以直接標(biāo)注@EntityListeners實體監(jiān)聽器,他的作用范圍僅在其所有繼承類中,并且實體監(jiān)聽器同樣可以保被其子類繼承或重載。
- 標(biāo)注為@MappedSuperclass的類其屬性最好設(shè)置為protected或default類型的,以保證其同一個包下的子類可以直接調(diào)用它的屬性。便于實體監(jiān)聽器或帶參數(shù)構(gòu)造函數(shù)的操作。
2.@Id
@Id
注解可將實體Bean
中某個屬性定義為主鍵。
3.@GeneratedValue
通過annotation來映射hibernate實體的,基于annotation的hibernate主鍵標(biāo)識為@Id,
其生成規(guī)則是由@GeneratedValue設(shè)定的。這里的@id和@GeneratedValue都是JPA的標(biāo)準(zhǔn)用法。
GenerationType:
public enum GenerationType{
TABLE,
SEQUENCE,
IDENTITY,
AUTO
}
JPA提供的四種標(biāo)準(zhǔn)用法為TABLE,SEQUENCE,IDENTITY,AUTO。
a,TABLE:使用一個特定的數(shù)據(jù)庫表格來保存主鍵。
b,SEQUENCE:根據(jù)底層數(shù)據(jù)庫的序列來生成主鍵,條件是數(shù)據(jù)庫支持序列。
c,IDENTITY:主鍵由數(shù)據(jù)庫自動生成(主要是自動增長型)
d,AUTO:主鍵由程序控制。
4.@JoinColumn
@OneToOne注釋只能確定實體與實體的關(guān)系是一對一的關(guān)系,不能指定數(shù)據(jù)庫表中的保存的關(guān)聯(lián)字段。所以此時要結(jié)合@JoinColumn標(biāo)記來指定保存實體關(guān)系的配置。
@JoinColumn與@Column標(biāo)記一樣,是用于注釋表中的字段的。它的屬性與@Column屬性有很多相同之處
@JoinColumn與@Column相區(qū)別的是:@JoinColumn注釋的是保存表與表之間關(guān)系的字段,它要標(biāo)注在實體屬性上。而@Column標(biāo)注的是表中不包含表關(guān)系的字段。
與@Column標(biāo)記一樣,name屬性是用來標(biāo)識表中所對應(yīng)的字段的名稱。例如customer表中存在字段addr_id,標(biāo)識的代碼如下所示。
兩張表結(jié)構(gòu)如下
TABLE_A:
ID, COLA1, COLA2
TABLE_B:
ID, A_ID, COLB1, COLB2
A和B是一對多的關(guān)系。
我在B的BEAN上面,通過Anotation
建立如下關(guān)系。
@ManyToOne(cascade = CascadeType.REFRESH, targetEntity = TABLE_A.class)
@JoinColumn(name = "A_ID", referencedColumnName = "ID", nullable = true, insertable = false, updatable = false)
5.Hibernate的集合映射cascade
1)到底在哪兒使用cascade="..."
cascade屬性并不是多對多關(guān)系一定要使用的,有了它只是讓我們在插入或者刪除對象時更加方便一些。只要在cascade的源頭上插入或者刪除,所有cascade的關(guān)系就會被自己動的插入或者刪除。便是為了能正確的cascade,unsaved-value的話,那說明這個對象不是persistence object要save(insert);如果id是非unsaved-value的話,那說明這個兌現(xiàn)格式persistence object(數(shù)據(jù)庫已經(jīng)存在),只要update就行。saveOrUpdate方法用的也是這個機制。
cascade屬性的可能值有:
all:所有情況下均進(jìn)行關(guān)聯(lián)操作,即save-update和delete。
none:所有情況下均不進(jìn)行關(guān)聯(lián)操作。這個是默認(rèn)值。
save-update:在執(zhí)行save/update/saveOrUpdate時進(jìn)行關(guān)聯(lián)操作。
delete:在執(zhí)行delete 時進(jìn)行關(guān)聯(lián)操作.
all-delete-orphan: 當(dāng)一個節(jié)點在對象圖中成為孤兒節(jié)點時,刪除該節(jié)點。比如在一個一對多的關(guān)系中,Student包含多個book,當(dāng)在對象關(guān)系中刪除一個book時,此book即成為孤兒節(jié)點。
6.@ApiModel
屬于swagger注解。
7.@Transient
ORM框架將忽略該屬性;
如果一個屬性并非數(shù)據(jù)庫表的字段映射,就務(wù)必將其標(biāo)示為@Transient,否則ORM框架默認(rèn)其注解為@Basic;
表示該字段在數(shù)據(jù)庫表中沒有。
@Transient
public int getAge() {
return 1+1;
}
注意:
//子字典項
@OneToMany(mappedBy = "parent")
@JsonIgnore(value = true)
List<Dict> subdicts;
只有OneToOne,OneToMany,ManyToMany上才有mappedBy屬性,ManyToOne不存在該屬性.mappedBy標(biāo)簽一定是定義在被擁有方的,他指向擁有方;
mappedBy的含義,應(yīng)該理解為,擁有方能夠自動維護(hù)跟被擁有方的關(guān)系,當(dāng)然,如果從被擁有方,通過手工強行來維護(hù)擁有方的關(guān)系也是可以做到的;
mappedBy跟joinColumn/JoinTable總是處于互斥的一方,可以理解為正是由于擁有方的關(guān)聯(lián)被擁有方的字段存在,擁有方才擁有了被擁有方。mappedBy這方定義JoinColumn/JoinTable總是失效的,不會建立對應(yīng)的字段或者表。
例子:
人跟身份證雙向關(guān)聯(lián)
在person里面定義的注釋代碼:
@OneToOne(cascade = CascadeTye.ALL,optional = true)
public IDCard getIdCard(){
return idCard;
}
//Jackson相關(guān):
8.@JsonIgnoreProperties
此注解是類注解,作用是json序列化時將java bean中的一些屬性忽略掉,序列化和反序列化都受影響。
9.@JsonIgnore
此注解用于屬性或者方法上(最好是屬性上),作用和上面的@JsonIgnoreProperties一樣。
10.@JsonSerialize
此注解用于屬性或者getter方法上,用于在序列化時嵌入我們自定義的代碼,比如序列化一個double時在其后面限制兩位小數(shù)點。
11.@JsonDeserialize
此注解用于屬性或者setter方法上,用于在反序列化時可以嵌入我們自定義的代碼,類似于上面的@JsonSerialize
12.@SuppressWarnings
在Java編譯過程中會出現(xiàn)很多警告,有很多是安全的,但是每次編譯有很多警告影響我們對error的過濾和修改,我們可以在代碼中加上:@SuppressWarnings(“XXXX”) 來解決
例如:@SuppressWarnings("deprecation")表示不顯示使用了不贊成使用的類或方法時的警告
13.@Repository
spring中的注解。
用于標(biāo)注數(shù)據(jù)訪問組件,即Dao組件。
在一個稍大的項目中,如果組件采用xml的bean定義來配置,顯然會增加配置文件的體積,查找以及維護(hù)起來也不太方便。
Spring2.5為我們引入了組件自動掃描機制,他在類路徑下尋找標(biāo)注了上述注解的類,并把這些類納入進(jìn)spring容器中管理。
它的作用和在xml文件中使用bean節(jié)點配置組件時一樣的。要使用自動掃描機制,我們需要打開以下配置信息:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package=”com.你的項目.你的項目”>
</beans>
- @Repository、@Service、@Controller 和 @Component
spring從2.0開始逐步引入一些注釋用于簡化Spring的開發(fā),@Repository注解是2.5引入的。用于將數(shù)據(jù)訪問層(Dao層)的類標(biāo)識為Spring Bean。具體只需要將該注解標(biāo)注在Dao類上即可。
同時,為了讓Spring能夠掃描類路徑中的類并識別出@Repository注解,需要在XML配置文件中棄用Bean的自動掃描功能,這可以通過<context:component-scan/>
實現(xiàn)。
如此的話,就不需要我們在XML中顯示使用<bean/>
去配置bean。Spring在容器初始化時將自動掃描base-package指定的包以及包下的所有java文件,所有標(biāo)注了@Respository的類都會被注冊為SpringBean。
注意:@Repository只能標(biāo)注在Dao類上。
因為該注解的作用不只是將類識別為Bean。同事還能降所有標(biāo)注中跑出的數(shù)據(jù)訪問異常封裝為Spring的數(shù)據(jù)訪問異常類型。Spring本身提供了一個豐富的并且是與具體的數(shù)據(jù)訪問技術(shù)無關(guān)的數(shù)據(jù)訪問異常機構(gòu),用于封裝不同的持久層框架拋出的異常,使得異常獨立于底層的框架。
Spring2.5在@Repository的基礎(chǔ)上增加了功能累死的額外三個注解:@Component,@Service,@Controller
。
它們分別用于軟件系統(tǒng)的不同層次:
1)@Component: 是一個泛化的概念,僅僅表示一個組件(Bean),可以作用在任何層次。
2)@Service: 通常作用在業(yè)務(wù)層,但是目前該功能與@Component相同。
3)@Controller:通常作用在控制層,但是目前該功能與@Component相同。
通過在類上使用@Repository、@Component、@Service 和 @Constroller
注解,Spring會自動創(chuàng)建相應(yīng)的 BeanDefinition 對象,并注冊到 ApplicationContext 中。這些類就成了Spring受管組件。這三個注解除了作用于不同的軟件層次的類,其使用方式與@Repository是完全相同的。
另外,除了上面的四個注解外,用戶可以創(chuàng)建自定義的注解,然后在注解上標(biāo)注 @Component,那么,該自定義注解便具有了與所@Component 相同的功能。不過這個功能并不常用。
當(dāng)一個 Bean 被自動檢測到時,會根據(jù)那個掃描器的 BeanNameGenerator 策略生成它的 bean名稱。默認(rèn)情況下,對于包含 name 屬性的 @Component、@Repository、 @Service 和@Controller,會把 name 取值作為 Bean 的名字。如果這個注解不包含 name值或是其他被自定義過濾器發(fā)現(xiàn)的組件,默認(rèn) Bean 名稱會是小寫開頭的非限定類名。如果你不想使用默認(rèn) bean命名策略,可以提供一個自定義的命名策略。首先實現(xiàn) BeanNameGenerator接口,確認(rèn)包含了一個默認(rèn)的無參數(shù)構(gòu)造方法。然后在配置掃描器時提供一個全限定類名,如下所示:
<beans ...>
<context:component-scan
base-package="a.b" name-generator="a.SimpleNameGenerator"/>
</beans>
與通過 XML 配置的 Spring Bean 一樣,通過上述注解標(biāo)識的Bean,其默認(rèn)作用域是"singleton",為了配合這四個注解,在標(biāo)注 Bean 的同時能夠指定 Bean 的作用域,Spring2.5 引入了 @Scope 注解。使用該注解時只需提供作用域的名稱就行了,如下所示:
@Scope("prototype")
@Repository
public class Demo { … }
如果你想提供一個自定義的作用域解析策略而不使用基于注解的方法,只需實現(xiàn) ScopeMetadataResolver接口,確認(rèn)包含一個默認(rèn)的沒有參數(shù)的構(gòu)造方法。然后在配置掃描器時提供全限定類名:
<context:component-scan base-package="a.b"
scope-resolver="footmark.SimpleScopeResolver" />
注意:@Scope("prototype") 是多例,默認(rèn)是單例的。
單例是不安全的,會導(dǎo)致屬性重復(fù)使用。
最佳實踐:
1、不要在controller
中定義成員變量。
2、萬一必須要定義一個非靜態(tài)成員變量時候,則通過注解@Scope("prototype")
,將其設(shè)置為多例模式。
15.@Autowired 注解與自動裝配
我們編寫spring 框架的代碼時候。一直遵循是這樣一個規(guī)則:所有在spring中注入的bean 都建議定義成私有的域變量。并且要配套寫上 get 和 set方法。
Spring 2.5引入了@Autowired注解,它可以對類成員變量,方法以及構(gòu)造函數(shù)進(jìn)行標(biāo)注,完成自動裝配的工作。通過@Autowired的使用來消除set,get方法。
在applicationContext.xml中加入:
<!-- 該 BeanPostProcessor 將自動對標(biāo)注 @Autowired 的 Bean 進(jìn)行注入 -->
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
Spring 通過一個 BeanPostProcessor 對 @Autowired 進(jìn)行解析,所以要讓 @Autowired
起作用必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean
。
package com.baobaotao;
import org.springframework.beans.factory.annotation.Autowired;
public class Boss {
@Autowired
private Car car;
@Autowired
private Office office;
…
}
當(dāng) Spring 容器啟動時,AutowiredAnnotationBeanPostProcessor 將掃描 Spring 容器中所有 Bean,當(dāng)發(fā)現(xiàn) Bean 中擁有 @Autowired 注釋時就找到和其匹配(默認(rèn)按類型匹配)的 Bean,并注入到對應(yīng)的地方中去。
@Autowired 將查找被標(biāo)注的方法的入?yún)㈩愋偷?Bean,并調(diào)用方法自動注入這些 Bean。而下面的使用方法則對構(gòu)造函數(shù)進(jìn)行標(biāo)注:
package com.baobaotao;
public class Boss {
private Car car;
private Office office;
@Autowired
public Boss(Car car ,Office office){
this.car = car;
this.office = office ;
}
…
}
由于 Boss() 構(gòu)造函數(shù)有兩個入?yún)ⅲ謩e是 car 和 office,@Autowired 將分別尋找和它們類型匹配的 Bean,將它們作為 Boss(Car car ,Office office) 的入?yún)韯?chuàng)建 Boss Bean。
16.@Transactional的使用方法
http://www.cnblogs.com/yepei/p/4716112.html
http://blog.csdn.net/andyzhaojianhui/article/details/51984157
事務(wù)管理對于企業(yè)應(yīng)用來說是至關(guān)重要的,即使出現(xiàn)異常情況,它也可以保證數(shù)據(jù)的一致性。
注意:一般,保存的時候,Service需要把事物加上:
@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED, readonly=false)
public void saveCommonMsg(Msg msg) {
}
17.@SuppressWarnings可以抑制一些能通過編譯但是存在有可能運行異常的代碼會發(fā)出警告,你確定代碼運行時不會出現(xiàn)警告提示的情況下,可以使用這個注釋。
("serial") 是序列化警告,當(dāng)實現(xiàn)了序列化接口的類上缺少serialVersionUID屬性的定義時,會出現(xiàn)黃色警告。可以使用@SuppressWarnings將警告關(guān)閉
18.Transient
Hibernate的一個注解
@Transient
表示該屬性并非一個到數(shù)據(jù)庫表的字段的映射,ORM框架將忽略該屬性.
//根據(jù)birth計算出age屬性
@Transient
public int getAge() {
return getYear(new Date()) - getYear(birth);
}