它是Spring基於ORM框架、JPA規範封裝的一套JPA應用框架,可以使開發者用極簡的代碼便可實現對數據的訪問和操做。它提供了包括增刪改查等在內的經常使用功能,且易於擴展。學習並使用Spring Data JPA能夠極大提升開發效率。html
配置文件一:applicationContext.xml(Spring上下文)java
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" default-lazy-init="true"> <!--第一步--> <!--定義服務層代碼存放的包掃描路徑--> <context:component-scan base-package="com.zang.usermanage.service" /> <!--第二步--> <!--定義實體的工廠bean--> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="userPU" /> <property name="persistenceXmlLocation" value="classpath:persistence.xml"></property> </bean> <!--第三步--> <!--定義事務管理器--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!--第四步--> <!--定義repository接口的存放目錄--> <!--定義接口實現的後綴,一般用Impl--> <!--定義實體工廠的引用--> <!--定義事務管理器的引用--> <jpa:repositories base-package="com.zang.usermanage.repository" repository-impl-postfix="Impl" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/> <!--第五步--> <!--聲明採用註解的方式申明事務--> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
配置文件二:persistence.xml(管理持久化)mysql
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> <persistence-unit name="userPU" transaction-type="RESOURCE_LOCAL"> <!--jpa的提供者--> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <!--聲明數據庫鏈接的驅動--> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> <!--jdbc數據庫的鏈接地址--> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/user_manage"/> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.password" value="123"/> <!--配置方言--> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> <!--激活查詢日誌功能--> <property name="hibernate.show_sql" value="true"/> <!--優雅地輸出Sql--> <property name="hibernate.format_sql" value="true"/> <!--添加一條解釋型標註--> <property name="hibernate.use_sql_comments" value="false"/> <!--配置如何根據java模型生成數據庫表結構,經常使用update,validate--> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
User.java(用戶實體類),UserRepository.java(用戶的數據接口,繼承JpaRepository接口), UserService.java(用戶服務接口),UserServiceImpl.java(接口實現), UserNotFound.java(異常類,在查詢實體未找到時拋出)spring
類之間關係sql
User.java(用戶實體類)數據庫
package com.zang.usermanage.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; /* 實體中經常使用的註解: @Entity :聲明這個類是一個實體類 @Table:指定映射到數據庫的表格 @Id :映射到數據庫表的主鍵屬性,一個實體只能有一個屬性被映射爲主鍵 @GeneratedValue:主鍵的生成策略 */ @Entity @Table(name="user") public class User { @Id @GeneratedValue private Integer id; private String name; private String address; private String phone; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
UserRepository.java(用戶的數據接口) 編程
package com.zang.usermanage.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.zang.usermanage.model.User; public interface UserRepository extends JpaRepository<User,Integer> { }
接口源碼以下:(實現類爲org.springframework.data.jpa.repository.support.SimpleJpaRepository.class)app
package org.springframework.data.jpa.repository; import java.io.Serializable; import java.util.List; import org.springframework.data.domain.Sort; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.PagingAndSortingRepository; @NoRepositoryBean public abstract interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> { public abstract List<T> findAll(); public abstract List<T> findAll(Sort paramSort); public abstract List<T> findAll(Iterable<ID> paramIterable); public abstract <S extends T> List<S> save(Iterable<S> paramIterable); public abstract void flush(); public abstract <S extends T> S saveAndFlush(S paramS); public abstract void deleteInBatch(Iterable<T> paramIterable); public abstract void deleteAllInBatch(); public abstract T getOne(ID paramID); }
UserService.java(用戶服務接口)框架
package com.zang.usermanage.service; import java.util.List;import com.zang.usermanage.exception.UserNotFound; import com.zang.usermanage.model.User; public interface UserService { //添加用戶 public void addUser(User user); //修改用戶 public User updateUser(User user) throws UserNotFound; //刪除用戶,根據用戶編號刪除 public User deleteUser(int id) throws UserNotFound; //查詢單個用戶 public User getUser(int id); //查詢全部用戶 public List<User> getUsers(); }
UserServiceImpl.java(接口實現)dom
package com.zang.usermanage.service; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service; import com.zang.usermanage.exception.UserNotFound; import com.zang.usermanage.model.User; import com.zang.usermanage.repository.UserRepository; @Service("userService") public class UserServiceImpl implements UserService { //自動裝配 @Autowired private UserRepository userRepository; //增長用戶調用save方法 @Override public void addUser(User user) { userRepository.save(user); } //更新用戶先進行非空判斷,再對新用戶各個屬性進行非空判斷並賦值,最後調用save方法 //自定義異常類 UserNotFound @Override public User updateUser(User user) throws UserNotFound { User userUpdate = userRepository.findOne(user.getId()); if (userUpdate==null) throw new UserNotFound(); if (user.getName()!=null) userUpdate.setName(user.getName()); if (user.getAddress()!=null) userUpdate.setAddress(user.getAddress()); if (user.getPhone()!=null) userUpdate.setPhone(user.getPhone()); userRepository.save(userUpdate); return userUpdate; } //刪除用戶先進行非空判斷,最後調用delete方法 @Override public User deleteUser(int id) throws UserNotFound { User userDelete = userRepository.findOne(id); if (userDelete==null) throw new UserNotFound(); userRepository.delete(userDelete); return userDelete; } //查詢單個,調用findOne方法 @Override public User getUser(int id) { return userRepository.findOne(id); } //查詢全部,調用findAll方法 @Override public List<User> getUsers() { return userRepository.findAll(); } }
Client.java(測試類)
package com.zang.usermanage.test; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.data.domain.Page; import com.zang.usermanage.exception.UserNotFound; import com.zang.usermanage.model.User; import com.zang.usermanage.service.UserService; public class Client { public static void printUser(User user){ StringBuilder sb = new StringBuilder(); sb.append("id="+user.getId()); sb.append("name="+user.getName()); sb.append("address="+user.getAddress()); sb.append("phone="+user.getPhone()); System.out.println(sb.toString()); } public static void testList(UserService userService){ List<User> users = userService.getUsers(); if (users!=null){ for (int i=0; i<users.size();i++){ printUser(users.get(i)); } } } public static void testUpate(UserService userService) throws UserNotFound{ User user = new User(); user.setId(1); user.setAddress("北京路121號"); userService.updateUser(user); testList(userService); } public static void testAdd(UserService userService){ User user = new User(); user.setAddress("天河路120號"); user.setName("小徐"); user.setPhone("130000000"); userService.addUser(user); testList(userService); } public static void testDelete(UserService userService) throws UserNotFound{ userService.deleteUser(7); testList(userService); } public static void main(String[] arg) throws UserNotFound{ ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) ac.getBean("userService"); //testList(userService); testUpate(userService); //testAdd(userService); //testDelete(userService); } }
JpaRepository支持接口規範方法名查詢。意思是若是在接口中定義的查詢方法符合它的命名規則,就能夠不用寫實現。
例如:findByName這個方法表示從數據庫中查詢Name這個屬性等於XXX的全部記錄,相似於SQL語句:select * from xxTable where name=xxx這種形式
這段話有兩個重點:
find+全局修飾+By+實體的屬性名稱+限定詞+鏈接詞+ ...(其它實體屬性)+OrderBy+排序屬性+排序方向 例如:findDistinctByFirstNameIgnoreCaseAndLastNameOrderByAgeDesc(String firstName,String lastName){......}
其中:Distinct是全局修飾(非必須),FirstName和LastName是實體的屬性名,And是鏈接詞,IgnoreCase是限定詞,Age是排序屬性,Desc是排序方向,限定詞和鏈接詞統稱爲「關鍵詞」。
經常使用詞以下:
更多關鍵詞請查看官方在線文檔: https://docs.spring.io/spring-data/jpa/docs/2.0.4.RELEASE/reference/html/
構詞法:主實體中子實體的名稱+ _ +子實體的屬性名稱
例如:List<Person> findByAddress_ZipCode(ZipCode zipCode) 表示查詢全部 Address(地址)的zipCode(郵編)爲指定值的全部Person(人員)
UserRepository接口定義查詢方法
package com.zang.usermanage.repository; import java.util.List; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import com.zang.usermanage.model.User; public interface UserRepository extends JpaRepository<User,Integer> { //查詢需求: 從數據庫中查詢電話號碼(phone)以指定字符串開始(例如:136)的,而且地址(address)中包含指定字符串(例如:路)的記錄 提取前兩條,降序排列 //select * from user where phone like '136%' and address like '%路%' order by phone desc limit 0,2 List<User> findTop2ByPhoneStartingWithAndAddressContainingOrderByPhoneDesc(String phone,String address); List<User> findTop2ByPhoneStartingWithAndAddressContaining(String phone,String address,Sort sort); //分頁要用到Pageable接口 Page<User> findByPhoneStartingWithAndAddressContaining(String phone,String address,Pageable pageable); }
UserService.java
package com.zang.usermanage.service; import java.util.List; import org.springframework.data.domain.Page; import com.zang.usermanage.exception.UserNotFound; import com.zang.usermanage.model.User; public interface UserService { //不分頁帶條件查詢 public List<User> getUsersByConditionNoPage(String phone,String address); //帶分頁條件查詢(須要獲得用戶列表而且獲得分頁信息) public Page<User> getUsersByConditionWithPage(String phone,String address,Integer page,Integer pageSize); //帶分頁條件查詢(獲得用戶列表) //public List<User> getUsersByCondition(String phone,String address,Integer page,Integer pageSize); }
UserServiceImpl.java
package com.zang.usermanage.service; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; import org.springframework.stereotype.Service; import com.zang.usermanage.exception.UserNotFound; import com.zang.usermanage.model.User; import com.zang.usermanage.repository.UserRepository; @Service("userService") public class UserServiceImpl implements UserService { //自動裝配 @Autowired private UserRepository userRepository; @Override public Page<User> getUsersByConditionWithPage(String phone,String address,Integer page,Integer pageSize) { //不排序 Page<User> userPage = userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new PageRequest(page, pageSize)); //排序(三種方法) //第一種排序方式 //Page<User> userPage = userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new PageRequest(page, pageSize,new Sort(Direction.ASC,"name","phone"))); //第二種排序方式 //Order order = new Order(Direction.ASC,"phone"); //Page<User> userPage = userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new PageRequest(page, pageSize,new Sort(order)); //第三種排序方式 //List<Order> orders = new ArrayList<Order>(); //orders.add(new Order(Direction.DESC,"name")); //orders.add(new Order(Direction.ASC,"phone")); //Page<User> userPage = userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new PageRequest(page, pageSize,new Sort(orders)); return userPage; } /** * 不分頁 */ @Override public List<User> getUsersByConditionNoPage(String phone,String address) { return userRepository.findTop2ByPhoneStartingWithAndAddressContainingOrderByPhoneDesc(phone, address); //return userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone, address, new Sort(Direction.ASC,"phone")); //Order order = new Order(Direction.ASC,"phone"); //return userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone, address, new Sort(order)); //List<Order> orders = new ArrayList<Order>(); //orders.add(new Order(Direction.DESC,"name")); //orders.add(new Order(Direction.ASC,"phone")); //return userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone, address, new Sort(orders); } }
Client.java(測試類)
package com.zang.usermanage.test; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.data.domain.Page; import com.zang.usermanage.exception.UserNotFound; import com.zang.usermanage.model.User; import com.zang.usermanage.service.UserService; public class Client { public static void printUser(User user){ StringBuilder sb = new StringBuilder(); sb.append("id="+user.getId()); sb.append("name="+user.getName()); sb.append("address="+user.getAddress()); sb.append("phone="+user.getPhone()); System.out.println(sb.toString()); } /** * 打印分頁信息 * @param pageInfo */ public static <T> void printPageInfo(Page<T> pageInfo){ StringBuilder sb = new StringBuilder(); sb.append("當前是第幾頁="+pageInfo.getNumber()).append("\n"); sb.append("當前頁查得的記錄數="+pageInfo.getNumberOfElements()).append("\n"); sb.append("每頁須要查詢的條數="+pageInfo.getSize()).append("\n"); sb.append("總共符合條件的記錄數="+pageInfo.getTotalElements()).append("\n"); sb.append("總共的頁數是="+pageInfo.getTotalPages()).append("\n"); System.out.println(sb.toString()); } /** * 不分頁查詢 * @param userService */ public static void testListByConditonNoPage(UserService userService){ List<User> users = userService.getUsersByConditionNoPage("136","路"); if (users!=null){ for (int i=0; i<users.size();i++){ printUser(users.get(i)); } } } /** * 分頁查詢 * @param userService */ public static void testListByConditonWithPage(UserService userService){ //傳入條件和分頁信息 Page<User> userPage = userService.getUsersByConditionWithPage("136","路",0,2); //打印分頁信息 printPageInfo(userPage); List<User> users = userPage.getContent(); if (users!=null){ for (int i=0; i<users.size();i++){ printUser(users.get(i)); } } } public static void main(String[] arg) throws UserNotFound{ ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) ac.getBean("userService"); //testListByConditonNoPage(userService); testListByConditonWithPage(userService); } }
效果: