Google Code Prettify

2017年1月8日 星期日

spring data: CrudRepository 自動生成

spring 專案針對 ORM 獨立出一個命名為 spring data 的專案,使用 spring data 可以更簡化程式設計,回頭看一下「JPA + Hibernate + Spring + JUnit (annotation)」,現在要將它用 spring data 改寫 …
  • 修改 JpaConfig
在類別的開頭加上紅色部份,指出要使用的 entityManagerFactory 及 transactionManager,還有就是要載入那些 package 下符合條件的介面,也就是繼承了 spring data 為方便程式開發者提供的一些制式介面,用來簡化程式,這些介面包含有 CrudPository、PagingAndSortingRepository、JpaRepository。
 1 @Configuration
 2 @EnableTransactionManagement
 3 @EnableJpaRepositories (
 4     basePackages = "idv.steven.invitation.database.dao",
 5     entityManagerFactoryRef = "entityManagerFactory",
 6     transactionManagerRef = "jpaTransactionManager"
 7 )
 8 public class JpaConfig {
 9     @Bean
10     public DataSource dataSource() {
11         BasicDataSource ds = new BasicDataSource();
12         ds.setDriverClassName("oracle.jdbc.OracleDriver");
13         ds.setUrl("jdbc:oracle:thin:@192.168.0.102:1521:DemoDB");
14         ds.setUsername("steven");
15         ds.setPassword("P@ssw0rd");
16         ds.setInitialSize(5);
17         
18         return ds;
19     }
20     
21     @Bean
22     public JpaVendorAdapter jpaVendorAdapter() {
23         HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
24         
25         adapter.setDatabase(Database.ORACLE);
26         adapter.setShowSql(true);
27         adapter.setGenerateDdl(false);
28         adapter.setDatabasePlatform("org.hibernate.dialect.Oracle10gDialect");
29         
30         return adapter;
31     }
32     
33     @Bean
34     public PlatformTransactionManager jpaTransactionManager() {
35         JpaTransactionManager tm = new JpaTransactionManager();
36         tm.setEntityManagerFactory(this.entityManagerFactory().getObject());
37         
38         return tm;
39     }
40         
41     @Bean
42     public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
43         LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
44         emf.setDataSource(this.dataSource());
45         emf.setPackagesToScan(new String[] {"idv.steven.invitation.database.dao", "idv.steven.invitation.database.entity" });
46         emf.setJpaVendorAdapter(this.jpaVendorAdapter());
47         
48         return emf;
49     }
50 }
  • 刪除 UsersDAOImpl 類別,並修改 UsersDAO 介面。
1 public interface UsersDAO extends CrudRepository<Users, String> {
2     
3 }
讓我們開發的介面繼承 CrudRepository,spring data 就會提供一些制式的 method,並自動產生實作的程式碼。在 CrudRepository 後面的 Users 及 String,分別指出 Entity 及 primary key 的型別。CrudRepository 提供的制式 method 如下: (參考 Professional Java for Web Applications: Featuring Websockets, Spring Framework, JPA Hibernate, and Spring Security 一書,p.  638.)
count() returns a long representing the total number of unfiltered entities extending T.
delete(T) and delete(ID) delete the single, specified entity, whereas delete(Iterable<? extends T>) deletes multiple entities and deleteAll() deletes every entity of that type.
exists(ID) returns a boolean indicating whether the entity of this type with the given surrogate key exists.
findAll() returns all entities of type T, whereas findAll(Iterable<ID>) returns the entities of type T with the given surrogate keys. Both return Iterable<T>.
findOne(ID) retrieves a single entity of type T given its surrogate key.
save(S) saves the given entity (insert or update) of type S where S extends T, and returns S, the saved entity.
save(Iterable<S>) saves all the entities (again, S extends T) and returns the saved entities as a new Iterable<S>.
  • 測試
雖然 UsersDAO 介面裡沒有任何 method,但是我們可以直接調用 CrudRepository 提供的 method …
1 @Transactional
2 @Test
3 public void findTalking() {
4     Users users = dao.findOne("hi.steven@gmail.com");
5     List<Appointment> talking = users.getAppointments();
6     for(Appointment t:talking) {
7         System.out.println("結果:" + t.toString());
8     }
9 }




【題外話 - 在 build.gradle 中設定排除特定 jar 檔】
要管理 java 的 jar 檔不是一件簡單的事,所以陸續出現了 Maven、Gradle 等解決方案 (當然這兩個軟體不只在解決 jar 檔的相依性),我現在慣用的是 Gradle,很方便的它會幫我找到所有相依的 jar 檔。但是,也可能出現 jar 檔會同時有兩個,只是版本不一樣,因為 open source 本來就不可完全協調的很一致,一定會有使用不同版本 jar 的可能性存在,當系統很龐大時,引入的 open source 甚至 framework 很多時,很難找出那個 jar 檔是因為那個 framework 的相依 jar 檔而被引入,像是我最近遇到的就是 gradle 抓回來的 jar 檔,同時存在著 hibernate-jpa-2.0-api 及 hibernate-jpa-2.1-api,這樣程式當然會出問題,必須在 build.gradle 中將不需要的 jar 檔排除! 方法很簡單,在 build.gradle 檔裡加入如下設定:
configurations {
    runtime.exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
}
runtime.exclude 算是指令,指出要排除那個 jar 檔,重點在於後面的 group、module 值我們怎麼知道要填什麼? 以上面的設定來說,要排除的是 hibernate-jpa-2.0-api-1.0.1.Final.jar,那麼就先在 Google 裡搜尋「 hibernate jpa maven」找到 maven 的 repository,由裡面可以找到 gradle 要由 maven repository 取得 jar 檔所需要的設定,如下:
compile group: 'org.hibernate.javax.persistence', name: 'hibernate-jpa-2.0-api', version: '1.0.1.Final'
值有三個 group、name、version,將 group的值填入上面的 group,name 的值填入上面的 module,這樣就大功告成了!

沒有留言:

張貼留言