?? jpa開發(fā).txt
字號:
元數(shù)據(jù)屬性說明:
name:列名。
referencedColumnName:該列引用列的列名
columnDefinition: 定義建表時創(chuàng)建此列的DDL
下面的代碼說明Customer映射到兩個表,主表CUSTOMER,從表CUST_DETAIL,從表需要建立主鍵列CUST_ID,該列和主表的主鍵列id除了列名不同,其他定義一樣。
@Entity
@Table(name="CUSTOMER")
@SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID",referencedColumnName="id"))
public class Customer {
@Id(generate = GeneratorType.AUTO)
public Integer getId() {
return id;
}
}
下面的代碼說明Employee和EmployeeInfo是一對一關(guān)系,Employee的主鍵列id作為外鍵指向EmployeeInfo的主鍵列INFO_ID。
@Table(name = "Employee")
public class Employee {
@OneToOne
@PrimaryKeyJoinColumn(name = "id", referencedColumnName="INFO_ID")
EmployeeInfo info;
}
PrimaryKeyJoinColumns
如果entity class使用了復(fù)合主鍵,指定單個PrimaryKeyJoinColumn不能滿足要求時,可以用PrimaryKeyJoinColumns來定義多個PrimaryKeyJoinColumn。
元數(shù)據(jù)屬性說明:
value: 一個PrimaryKeyJoinColumn數(shù)組,包含所有PrimaryKeyJoinColumn。
下面的代碼說明了Employee和EmployeeInfo是一對一關(guān)系。他們都使用復(fù)合主鍵,建表時需要在Employee表建立一個外鍵,從Employee的主鍵列id,name指向EmployeeInfo的主鍵列INFO_ID和INFO_NAME.
@Entity
@IdClass(EmpPK.class)
@Table(name = "EMPLOYEE")
public class Employee {
private int id;
private String name;
private String address;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumns({
@PrimaryKeyJoinColumn(name="id", referencedColumnName="INFO_ID"),
@PrimaryKeyJoinColumn(name="name" , referencedColumnName="INFO_NAME")})
EmployeeInfo info;
}
@Entity
@IdClass(EmpPK.class)
@Table(name = "EMPLOYEE_INFO")
public class EmployeeInfo {
@Id
@Column(name = "INFO_ID")
private int id;
@Id
@Column(name = "INFO_NAME")
private String name;
}
Transient
Transient用來注釋entity的屬性,指定的這些屬性不會被持久化,也不會為這些屬性建表。
@Transient
private String name;
Version
Version指定實體類在樂觀事務(wù)中的version屬性。在實體類重新由EntityManager管理并且加入到樂觀事務(wù)中時,保證完整性。每一個類只能有一個屬性被指定為version,version屬性應(yīng)該映射到實體類的主表上。
下面的代碼說明versionNum屬性作為這個類的version,映射到數(shù)據(jù)庫中主表的列名是OPTLOCK。
@Version
@Column("OPTLOCK")
protected int getVersionNum() { return versionNum; }
Lob
Lob指定一個屬性作為數(shù)據(jù)庫支持的大對象類型在數(shù)據(jù)庫中存儲。使用LobType這個枚舉來定義Lob是二進制類型還是字符類型。
LobType枚舉類型說明:
BLOB 二進制大對象,Byte[]或者Serializable的類型可以指定為BLOB。
CLOB 字符型大對象,char[]、Character[]或String類型可以指定為CLOB。
元數(shù)據(jù)屬性說明:
fetch: 定義這個字段是lazy loaded還是eagerly fetched。數(shù)據(jù)類型是FetchType枚舉,默認(rèn)為LAZY,即lazy loaded.
type: 定義這個字段在數(shù)據(jù)庫中的JDBC數(shù)據(jù)類型。數(shù)據(jù)類型是LobType枚舉,默認(rèn)為BLOB。
下面的代碼定義了一個BLOB類型的屬性和一個CLOB類型的屬性。
@Lob
@Column(name="PHOTO" columnDefinition="BLOB NOT NULL")
protected JPEGImage picture;
@Lob(fetch=EAGER, type=CLOB)
@Column(name="REPORT")
protected String report;
JoinTable
JoinTable在many-to-many關(guān)系的所有者一邊定義。如果沒有定義JoinTable,使用JoinTable的默認(rèn)值。
元數(shù)據(jù)屬性說明:
table:這個join table的Table定義。
joinColumns:定義指向所有者主表的外鍵列,數(shù)據(jù)類型是JoinColumn數(shù)組。
inverseJoinColumns:定義指向非所有者主表的外鍵列,數(shù)據(jù)類型是JoinColumn數(shù)組。
下面的代碼定義了一個連接表CUST和PHONE的join table。join table的表名是CUST_PHONE,包含兩個外鍵,一個外鍵是CUST_ID,指向表CUST的主鍵ID,另一個外鍵是PHONE_ID,指向表PHONE的主鍵ID。
@JoinTable(
table=@Table(name=CUST_PHONE),
joinColumns=@JoinColumn(name="CUST_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="PHONE_ID", referencedColumnName="ID")
)
TableGenerator
TableGenerator定義一個主鍵值生成器,在Id這個元數(shù)據(jù)的generate=TABLE時,generator屬性中可以使用生成器的名字。生成器可以在類、方法或者屬性上定義。
生成器是為多個實體類提供連續(xù)的ID值的表,每一行為一個類提供ID值,ID值通常是整數(shù)。
元數(shù)據(jù)屬性說明:
name:生成器的唯一名字,可以被Id元數(shù)據(jù)使用。
table:生成器用來存儲id值的Table定義。
pkColumnName:生成器表的主鍵名稱。
valueColumnName:生成器表的ID值的列名稱。
pkColumnValue:生成器表中的一行數(shù)據(jù)的主鍵值。
initialValue:id值的初始值。
allocationSize:id值的增量。
下面的代碼定義了兩個生成器empGen和addressGen,生成器的表是ID_GEN。
@Entity public class Employee {
...
@TableGenerator(name="empGen",
table=@Table(name="ID_GEN"),
pkColumnName="GEN_KEY",
valueColumnName="GEN_VALUE",
pkColumnValue="EMP_ID",
allocationSize=1)
@Id(generate=TABLE, generator="empGen")
public int id;
...
}
@Entity public class Address {
...
@TableGenerator(name="addressGen",
table=@Table(name="ID_GEN"),
pkColumnValue="ADDR_ID")
@Id(generate=TABLE, generator="addressGen")
public int id;
...
}
SequenceGenerator
SequenceGenerator定義一個主鍵值生成器,在Id這個元數(shù)據(jù)的generator屬性中可以使用生成器的名字。生成器可以在類、方法或者屬性上定義。生成器是數(shù)據(jù)庫支持的sequence對象。
元數(shù)據(jù)屬性說明:
name:生成器的唯一名字,可以被Id元數(shù)據(jù)使用。
sequenceName:數(shù)據(jù)庫中,sequence對象的名稱。如果不指定,會使用提供商指定的默認(rèn)名稱。
initialValue:id值的初始值。
allocationSize:id值的增量。
下面的代碼定義了一個使用提供商默認(rèn)名稱的sequence生成器。
@SequenceGenerator(name="EMP_SEQ", allocationSize=25)
DiscriminatorColumn
DiscriminatorColumn定義在使用SINGLE_TABLE或JOINED繼承策略的表中區(qū)別不繼承層次的列。
元數(shù)據(jù)屬性說明:
name:column的名字。默認(rèn)值為TYPE。
columnDefinition:生成DDL的sql片斷。
length:String類型的column的長度,其他類型使用默認(rèn)值10。
下面的代碼定義了一個列名為DISC,長度為20的String類型的區(qū)別列。
@Entity
@Table(name="CUST")
@Inheritance(strategy=SINGLE_TABLE,
discriminatorType=STRING,
discriminatorValue="CUSTOMER")
@DiscriminatorColumn(name="DISC", length=20)
public class Customer { ... }
6.JPA的查詢語言
JPA的查詢語言是面向?qū)ο蠖敲嫦驍?shù)據(jù)庫的,它以面向?qū)ο蟮淖匀徽Z法構(gòu)造查詢語句,可以看成是Hibernate HQL的等價物。
簡單的查詢
你可以使用以下語句返回所有Topic對象的記錄:
SELECT t FROM Topic t
t表示Topic的別名,在Topic t是Topic AS t的縮寫。
如果需要按條件查詢Topic,我們可以使用:
SELECT DISTINCT t FROM Topic t WHERE t.topicTitle = ?1
通過WHERE指定查詢條件,?1表示用位置標(biāo)識參數(shù),爾后,我們可以通過Query的setParameter(1, "主題1")綁定參數(shù)。而DISTINCT表示過濾掉重復(fù)的數(shù)據(jù)。
如果需要以命名綁定綁定數(shù)據(jù),可以改成以下的方式:
SELECT DISTINCT t FROM Topic t WHERE t.topicTitle = :title
這時,需要通過Query的setParameter("title", "主題1")綁定參數(shù)。
關(guān)聯(lián)查詢:從One的一方關(guān)聯(lián)到Many的一方
返回PollOptions對應(yīng)的PollTopic對象,可以使用以下語句:
SELECT DISTINCT p FROM PollTopic p, IN(p.options) o WHERE o.optionItem LIKE ?1
這個語法和SQL以及HQL都有很大的區(qū)別,它直接實體屬性連接關(guān)聯(lián)的實體,這里我們通過PollTopic的options屬性關(guān)聯(lián)到PollOption實體上,對應(yīng)的SQL語句為:
SELECT DISTINCT t0.TOPIC_ID, t0.TOPIC_TYPE, t0.TOPIC_TITLE, t0.TOPIC_TIME, t0.TOPIC_VIEWS, t0.MULTIPLE, t0.MAX_CHOICES FROM T_TOPIC t0, T_POLL_OPTION t1 WHERE (((t1.OPTION_ITEM LIKE ?) AND (t0.TOPIC_TYPE = ?)) AND (t1.TOPIC_ID = t0.TOPIC_ID))
該查詢語句的另外兩種等價的寫法分別是:
SELECT DISTINCT p FROM PollTopic p JOIN p.options o WHERE o.optionItem LIKE ?1
和
SELECT DISTINCT p FROM PollTopic p WHERE p.options.optionItem LIKE ?1
關(guān)聯(lián)查詢:從Many的一方關(guān)聯(lián)到One的一方
從Many一方關(guān)聯(lián)到One一方的查詢語句和前面所講的也很相似。如我們希望查詢某一個調(diào)查主題下的所示調(diào)查項,則可以編寫以下的查詢語句:
SELECT p FROM PollOption p JOIN p.pollTopic t WHERE t.topicId = :topicId
對應(yīng)的SQL語句為:
SELECT t0.OPTION_ID, t0.OPTION_ITEM, t0.TOPIC_ID FROM T_POLL_OPTION t0, T_TOPIC t1 WHERE ((t1.TOPIC_ID = ?) AND ((t1.TOPIC_ID = t0.TOPIC_ID) AND (t1.TOPIC_TYPE = ?)))
使用其它的關(guān)系操作符
使用空值比較符,比如查詢附件不空的所有帖子對象:
SELECT p FROM Post p WHERE p.postAttach IS NOT NULL
范圍比較符包括BETWEEN..AND和>、>= 、<、<=、<>這些操作符。比如下面的語句查詢?yōu)g覽次數(shù)在100到200之間的所有論壇主題:
SELECT t FROM Topic t WHERE t.topicViews BETWEEN 100 AND 200
集合關(guān)系操作符
和其它實體是One-to-Many或Many-to-Many關(guān)系的實體,通過集合引用關(guān)聯(lián)的實體,我們可以通過集合關(guān)系操作符進行數(shù)據(jù)查詢。下面的語句返回所有沒有選項的調(diào)查論壇的主題:
SELECT t FROM PollTopic t WHERE t.options IS EMPTY
我們還可以通過判斷元素是否在集合中進行查詢:
SELECT t FROM PollTopic t WHERE :option MEMBER OF t.options
這里參數(shù)必須綁定一個PollOption的對象,JPA會自動將其轉(zhuǎn)換為主鍵比較的SQL語句。
子查詢
JPA可以進行子查詢,并支持幾個常見的子查詢函數(shù):EXISTS、ALL、ANY。如下面的語句查詢出擁有6個以上選項的調(diào)查主題:
SELECT t FROM PollTopic t WHERE (SELECT COUNT(o) FROM t.options o) > 6
可用函數(shù)
JPA查詢支持一些常見的函數(shù),其中可用的字符串操作函數(shù)有:
? CONCAT(String, String):合并字段串;
? LENGTH(String):求字段串的長度;
? LOCATE(String, String [, start]):查詢字段串的函數(shù),第一個參數(shù)為需要查詢的字段串,看它在出現(xiàn)在第二個參數(shù)字符串的哪個位置,start表示從哪個位置開始查找,返回查找到的位置,沒有找到返回0。如LOCATE ('b1','a1b1c1',1)返回為3;
? SUBSTRING(String, start, length):子字段串函數(shù);
? TRIM([[LEADING|TRAILING|BOTH] char) FROM] (String):將字段串前后的特殊字符去除,可以通過選擇決定具體的去除位置和字符;
? LOWER(String):將字符串轉(zhuǎn)為小寫;
? UPPER(String):將字符串轉(zhuǎn)為大寫。
數(shù)字操作函數(shù)有:
? ABS(number):求絕對值函數(shù);
? MOD(int, int):求模的函數(shù);
? SQRT(double):求平方函數(shù);
? SIZE(Collection):求集合大小函數(shù)。
更改語句
可以用EntityManager進行實體的更新操作,也可以通過查詢語言執(zhí)行數(shù)據(jù)表的字段更新,記錄刪除的操作:
下面的語句將某一個調(diào)查選項更新為新的值:
UPDATE PollOption p SET p.optionItem = :value WHERE p.optionId = :optionId
我們使用Query接口的executeUpdate()方法執(zhí)行更新。下面的語句刪除一條記錄:
DELETE FROM PollOption p WHERE p.optionId = :optionId
排序和分組
我們還可以對查詢進行排序和分組。如下面的語句查詢出主題的發(fā)表時間大于某個時間值,返回的結(jié)果按瀏覽量降序排列:
SELECT t FROM Topic t WHERE t.topicTime > :time ORDER BY t.topicViews DESC
下面的語句計算出每個調(diào)查主題對應(yīng)的選項數(shù)目:
SELECT COUNT(p),p.pollTopic.topicId FROM PollOption p GROUP BY p.pollTopic.topicId
這里,我們使用了計算數(shù)量的聚集函數(shù)COUNT(),其它幾個可用的聚集函數(shù)分別為:
? AVG:計算平均值,返回類型為double;
? MAX:計算最大值;
? MIN:計算最小值;
? SUM:計算累加和;
我們還可以通過HAVING對聚集結(jié)果進行條件過濾:
SELECT COUNT(p),p.pollTopic.topicId FROM PollOption p GROUP BY p.pollTopic.topicId HAVING p.pollTopic.topicId IN(1,2,3)
7.小結(jié)
在不久的將來,Sun可能會將JPA作為一個單獨的JSR對待,同時JPA還可能作為Java SE的一部分。不過這些都不太重要,重要的是,我們現(xiàn)在已經(jīng)可以在脫離容器的情況下、在Java SE應(yīng)用中使用JPA了。
JPA已經(jīng)作為一項對象持久化的標(biāo)準(zhǔn),不但可以獲得Java EE應(yīng)用服務(wù)器的支持,來可以直接在Java SE中使用。開發(fā)者將無需在現(xiàn)有多種ORM框架中艱難地選擇,按照Sun的預(yù)想,現(xiàn)有ORM框架頭頂?shù)墓猸h(huán)將漸漸暗淡,不再具有以往的吸引力。
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -