klg-jpa:spring-data-jpa 最佳實踐


klg-jpa:spring-data-jpa 最佳實踐

項目介紹

碼雲地址:https://gitee.com/klguang/klg-jpa

JPA是sun為POJO持久化制定的標准規范,用來操作實體對象,執行CRUD操作,讓開發者從繁瑣的JDBC和SQL代碼中解脫出來。 但是JPA有以下兩個缺陷:
1.臃腫的動態條件查詢 

2.眾所周知,復雜查詢(聯接表查詢)的效率低 
spring-data-jpa和mybatis可以整合在一起使用有什么優缺點,這個問答種了解到 spring-data-jpa-extra這個庫,讓我們可用更方便的寫sql查詢。

klg-jpa,spring-data-jpa 最佳實踐,用起來就像開了掛,更多例子klg-j2ee-dataacess-demo 演示

單表查詢最佳實踐

1. find by attribute是一種較靈活的方式,需要用到jpa生成的metamodel,在快速開發的利器 

BaseRepository api:

	//-------------find by attribute------------------------
	public Page<T> findPage(Pageable pageable,AttrExpression...exprs);
	public List<T> findList(Sort sort,AttrExpression...exprs);
	public List<T> findList(AttrExpression...exprs);
	public T getOne(AttrExpression...exprs);
	public long count(AttrExpression...exprs);

find by attribute 適合不定條件單表查詢,默認是不忽略空值的(null或者""),如果要忽略空值,請用AExpr屬性表達式構造器的igEmpty()方法。

Pageable pageable = new PageRequest(0, 10, new Sort(Direction.DESC, "userId"));
Page<User> userPage = userDAO.findPage(pageable, 
		AExpr.eq(User_.account, "").igEmpty(),
		AExpr.contain(User_.userName, "fd"));

含有開始和結束時間 動態查詢的處理

@ResponseBody
@RequestMapping("/findpage")
public EasyUIPage findpage(
	@RequestParam int page,
	@RequestParam int rows,
	@RequestParam(required=false) Long employeeid,
	@RequestParam(required=false) @DateTimeFormat(pattern="yyyy-MM-dd") Date startDate,
	@RequestParam(required=false) @DateTimeFormat(pattern="yyyy-MM-dd") Date endDate){
	Pageable pageable=new PageRequest(page<1?0:page-1, rows, new Sort(Direction.DESC,"numId"));
	_EmployeeName employeeName=employeeid==null?null:MyReflectUtil.createWithSet(_EmployeeName.class, "id", employeeid);

	Page<DrugOut> pageData=drugOutService.findPage(pageable, 
		AExpr.eq(DrugOut_.employeeName, employeeName).igEmpty(),
		AExpr.gte(DrugOut_.saledate, startDate).igEmpty(),
		AExpr.lte(DrugOut_.saledate, endDate).igEmpty());


	return new EasyUIPage(pageData);
}

注意: 
1).復雜屬性的表達式處理:先判斷復雜屬性的實體的id是否為空
2).動態查詢,參數(required=false)、查詢的屬性表達式列表(igEmpty)

2. 通過解析Repository中的方法名創建查詢,是spring-data-jpa的一大特色。符合經典的java三層架構:表現層(UI),業務邏輯層(BLL),數據訪問層(DAL) 

這是spring官網的例子:通過EmailAddress和Lastname來查找用戶

public interface UserRepository extends Repository<User, Long> {

  List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}

詳見spring-data-jpa#Query Creation

3. 頁面參數封裝到實體,然后運用qbe(query by example)。qbe會自動忽略null值 
BaseRepository api:

	//--------------qbe(query by example)--------------------
	public Page<T> findPage(T example,Pageable pageable);
	public List<T> findList(T example,Sort sort);
	public List<T> findList(T example);
	public T getOne(T example);
	public long count(T example);

qbe復雜查詢只支持String的模糊查詢,大於、小於、between and均不支持。
ExampleMatcher例字,嵌套屬性模糊匹配

//User有屬性logrole
ExampleMatcher matcher=ExampleMatcher.matching()
	.withMatcher("logrole.logRoleName", GenericPropertyMatcher.of(StringMatcher.CONTAINING).ignoreCase());
List<User> users=userDAO.findAll(Example.of(user,matcher));

詳見spirng-data-jpa#query-by-example

復雜查詢最佳實踐

復雜查詢,無論是用java代碼進行sql拼接還是臃腫的Criteria動態查詢都是不推薦的。因為這么做一方面是不夠優雅,更重要的是難以維護。Mybatis的流行給了我們很多啟發,復雜查詢用sql配置文件,是一種靈活且方便維護的方式。
以下兩種方式是我推薦大家使用的:

  1. 可用使用@NamedQuery,或spring-data-jpa的@Query
  2. 引入spring-data-jpa-extra這個庫

使用說明

  1. 下載本項目,並執行maven install ,在項目引入依賴
  2. 項目中Repository繼承BaseRepository,Service接口繼承BaseService,ServiceImpl繼承BaseServiceImpl;BaseService的接口中有BaseRepository的大部分方法
  3. spring配置如下:
	<!-- 指定 BaseRepositoryFactoryBean -->
	<jpa:repositories base-package="demo,com.slyak.spring.jpa"
		factory-class="klg.common.dataaccess.BaseRepositoryFactoryBean"
		entity-manager-factory-ref="entityManagerFactory"
		transaction-manager-ref="transactionManager" repository-impl-postfix="Impl" />
	
	<!-- 配置 freemarkerSqlTemplates解析相關-->
	<bean id="freemarkerSqlTemplates" class="com.slyak.spring.jpa.FreemarkerSqlTemplates">
		<property name="suffix" value=".sftl" />
		<property name="templateLocation" value="classpath*:/sqls"/>
	</bean>

如有疑問下載klg-j2ee-dataacess-demo 演示

注意

本項目依賴spring-data-jpa-extra-2.1.2.RELEASE,但我做了一些改動,然后打成jar包
項目地址:https://github.com/klguang/spring-data-jpa-extra/tree/2.1.2.RELEASE

  1. com.slyak.spring.jpa.ContextHolder 訪問控制為public,目的是讓原來項目中已經存在的BaseRepositoryFactoryBean能工作。
  2. 模板文件名為Entity的java full name
  3. 測試用例跑通


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM