jpa eclipse搭建過程和注意事項
環境:Eclipse Jpa2.0 jdk1.7 tomcat7
1、在eclipse中 一個jpa專案
建立完成後,可以看到建好的專案
Persistence.xml是jpa專案的全域性配置檔案
2、新增專案需要的jar包
antlr-2.7.7.jar
dom4j-1.6.1.jar
ehcache-core-2.4.3.jar
hibernate-commons-annotations-4.0.2.Final.jar
hibernate-core-4.2.4.Final.jar
hibernate-ehcache-4.2.4.Final.jar
hibernate-entitymanager-4.2.4.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
javassist-3.15.0-GA.jar
jboss-logging-3.1.0.GA.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
mysql-connector-java-5.1.7-bin.jar
ojdbc6.jar
slf4j-api-1.6.1.jar
這裡添加了兩個資料庫的驅動包,不是必須的,根據自己連線的資料庫來新增不同的驅動包
3、在src目錄下建立bean目錄,用於存放於資料庫關聯的實體類(本案例建立了三個實體類做演示,分別是:Account、Emp4、Dept6)
實體類可以手動建立,也可以通過工具生成
如果是jpa專案,可以通過在專案右鍵,選擇JPA Tools選項,裡面可以反向生成實體類
右側紅線框中,第一個是根據實體構建表,下面那個是根據表構建實體類
實體類注意事項:
如果單表操作無所謂,但是一旦涉及到多表操作,就會出現很多問題:
1) 資料型別要用Integer
2) 所有註解不要放在屬性上,要放在get方法上(不然也會出現在資料庫中生成關聯物件列)
3) 如果是自己新建的實體類,新增@Entity註解後,會出錯,需要在persistence.xml中引用此類才行(引用方式在下面會的persistence.xml檔案中會介紹);並且還要加上@ID註解,不然也會編譯錯誤
4、配置persistence.xml,完整的xml配置如下:
<?xmlversion="1.0"encoding="UTF-8"?> <persistenceversion="2.0"xmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unitname="jpa_test1"> <!-- 配置使用什麼 ORM產品來作為 JPA的實現 1. 實際上配置的是 javax.persistence.spi.PersistenceProvider介面的實現類 2. 若 JPA專案中只有一個 JPA的實現產品,則也可以不配置該節點. --> <provider>org.hibernate.ejb.HibernatePersistence</provider> <!-- 加入持久化類 --> <class>jpa_test1.Account</class> <class>jpa_test1.Emp4</class> <class>jpa_test1.Dept6</class> <!-- 配置二級快取的策略(不是必須) ALL:所有的實體類都被快取 NONE:所有的實體類都不被快取. ENABLE_SELECTIVE:標識 @Cacheable(true)註解的實體類將被快取 DISABLE_SELECTIVE:快取除標識 @Cacheable(false)以外的所有實體類 UNSPECIFIED:預設值,JPA產品預設值將被使用 --> <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> <properties> <!-- 連線資料庫的基本資訊 --> <propertyname="javax.persistence.jdbc.driver"value="oracle.jdbc.OracleDriver"/> <propertyname="javax.persistence.jdbc.url"value="jdbc:oracle:thin:@localhost:1521:orcl"/> <propertyname="javax.persistence.jdbc.user"value="scott"/> <propertyname="javax.persistence.jdbc.password"value="tiger"/> <!-- 配置 JPA實現產品的基本屬性.配置 hibernate的基本屬性(不是必須) --> <propertyname="hibernate.format_sql"value="true"/> <propertyname="hibernate.show_sql"value="true"/> <propertyname="hibernate.hbm2ddl.auto"value="update"/> <!-- 二級快取相關(不是必須) --> <propertyname="hibernate.cache.use_second_level_cache"value="true"/> <propertyname="hibernate.cache.region.factory_class"value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/> <propertyname="hibernate.cache.use_query_cache"value="true"/> </properties> </persistence-unit> </persistence>
5、建立一個test包,包中建立一個測試類,測試單表操作,程式碼如下:
public class MyTest {
public static void main(String[] args) {
String pname="jpa_test1";
//1、EntityManagerFactory相當於hibernate的sessionFactory
//有兩種建立方法,第一種是直接傳到persistence.xml中persistence-unit標籤的名稱
EntityManagerFactory facotry=Persistence.createEntityManagerFactory(pname);
//另一種是不管可以傳遞名字,還可以傳遞一些引數,如下面show_sql的引數來設定連線的配置
/*Map map=new HashMap();
map.put("hibernate.show_sql", false);
EntityManagerFactory facotry=Persistence.createEntityManagerFactory(pname);*/
//2、EntityManager相當於hibernate的session
EntityManager manager=facotry.createEntityManager();
//3、開啟事務
EntityTransaction tran=manager.getTransaction();
tran.begin();
//4、進行持久化操作
//插入,相當於hibernate的save(和hibernate的 save方法的不同之處:若物件有 id, 則不能執行 insert操作,而會丟擲異常. )
/*Account acc=newAccount();
acc.setUsername("jpatest1");
acc.setPassword("123");
manager.persist(acc);
//儲存完後可以獲取儲存成功的ID
System.out.println(acc.getAid());
*/
//find查詢,相當於hibernate的get方法
/*Account acc=manager.find(Account.class,1);
System.out.println(acc.getUsername());*/
//getReference,相當於hibernate的load方法(getReference只有使用查詢出來的物件才會傳送SQL,而get執行查詢就立即傳送SQL查詢)
Account acc=manager.getReference(Account.class, 1);
System.out.println(acc.getUsername());
//5、提交事務
tran.commit();
//6、關閉EntityManager
manager.close();
//7、關閉EntityManagerFactory
facotry.close();
}
}
-------------到此為止單表的jpa操作完畢------------
6、單向多對一
1) 在Emp6中,新建一個private Dept6 dept; 並且提供get/set和註解,配置如下:
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="deptid")
publicDept6 getDept() {
returndept;
}
publicvoid setDept(Dept6 dept) {
this.dept= dept;
}
2) 在測試類中進行測試
Dept6 dept=new Dept6();
dept.setDeptname("jpa1");
dept.setLoc("1111");
Emp4 emp1=newEmp4();
emp1.setEname("11");
emp1.setDept(dept);
Emp4 emp2=new Emp4();
emp2.setEname("222");
emp2.setDept(dept);
manager.persist(dept);//先儲存一方(如果資料庫已經有一方資料,需要做多對一的新增,也可以直接建立一個部門物件,設定一個id值,不一定非要先儲存dept,才能讓員工獲得一方dept物件,比如可以像橫線下面那段程式碼寫法)
manager.persist(emp1);//再儲存多方
manager.persist(emp2);
Dept6 dept=new Dept6();
dept.setId(5650);
Emp4 emp1=new Emp4();
emp1.setEname("11");
emp1.setDept(dept);
Emp4 emp2=new Emp4();
emp2.setEname("222");
emp2.setDept(dept);
manager.persist(emp1);
manager.persist(emp2);
6、單向一對多
1) 在Dept6中,新增如下集合,存放關聯的員工:
private Set<Emp4> emps=new HashSet<Emp4>();
並生成get/set和註解,配置如下:
//注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 屬性, 則 @OneToMany 端就不能再使用 @JoinColumn 屬性了.
@OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
@JoinColumn(name="deptid")
public Set<Emp4>getEmps() {
returnemps;
}
public voidsetEmps(Set<Emp4> emps) {
this.emps =emps;
}
注意: 定義的set集合需要new,並且需要指定泛型
2) 在測試類中進行測試,程式碼如下:
Dept6 dept=new Dept6();
dept.setDeptname("xxx");
Emp4 emp1=new Emp4();
emp1.setEname("11");
Emp4 emp2=new Emp4();
emp2.setEname("222");
dept.getEmps().add(emp1);
dept.getEmps().add(emp2);
manager.persist(dept);
6、JPQL查詢
1) 基礎jpql
String jpql = "FROM Customer c WHERE c.age > ?";
Query query= entityManager.createQuery(jpql);
//佔位符的索引是從 1 開始
query.setParameter(1,1);
List<Customer>customers = query.getResultList();
System.out.println(customers.size());
2) 如果只想查詢部分列,那麼集合將會存放陣列
如果查詢部分列,不想集合存放陣列,那麼需要給實體提供一個對應的建構函式,並如下查詢:
Stringjpql = "SELECT new Customer(c.lastName, c.age) FROM Customer c WHERE c.id> ?";
List result=
entityManager.createQuery(jpql).setParameter(1, 1).getResultList();
System.out.println(result);
3) 也可以通過createNamedQuery查詢實體類中已經寫好的jpql
@NamedQuery(name="testNamedQuery", query="FROM Customer cWHERE c.id = ?")//這裡eclipse可能會顯示錯誤,但是不影響執行,也可以寫成select c FROM Customer c WHERE c.id = ?
@Table(name="JPA_CUTOMERS")
@Entity
publicclass Customer {
Queryquery =
entityManager.createNamedQuery("testNamedQuery").setParameter(1,3);
Customercustomer = (Customer) query.getSingleResult();
System.out.println(customer);
4) 也可以使用sql語句查詢:
String sql = "SELECT age FROM jpa_cutomers WHERE id = ?";
Query query= entityManager.createNativeQuery(sql).setParameter(1, 3);
Objectresult = query.getSingleResult();
System.out.println(result);
5) 使用 hibernate 的查詢快取
在每次查詢後面跟上.setHint(QueryHints.HINT_CACHEABLE, true);
如:
第一次查詢:Query query =
entityManager.createQuery(jpql)
.setHint(QueryHints.HINT_CACHEABLE, true);
第二次查詢:query =
entityManager.createQuery(jpql)
.setHint(QueryHints.HINT_CACHEABLE, true);
6) 查詢時也可以使用OrderBy、GroupBy、關聯查詢、子查詢,如:
OrderBy:
String jpql = "FROM Customer c WHERE c.age > ? ORDER BY c.ageDESC";
GroupBy:
String jpql = "SELECT o.customer FROM Order o "
+"GROUP BY o.customer "
+"HAVING count(o.id) >= 2";
關聯查詢:
Stringjpql = "FROM Customer c LEFT OUTER JOIN FETCH c.orders WHERE c.id = ?";
子查詢:
String jpql = "SELECT o FROM Order o "
+ "WHERE o.customer = (SELECT c FROM Customer c WHERE c.lastName =?)";
7) 使用 jpql 自帶的函式
String jpql = "SELECT lower(c.email) FROM Customer c";
8) 可以使用 JPQL 完成 UPDATE 和 DELETE 操作
String jpql = "UPDATE Customer c SET c.lastName = ? WHERE c.id =?";