1. 程式人生 > >jpa eclipse搭建過程和注意事項

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 =?";