Spring Data開發(fā)手冊|手把手教你簡化持久層開發(fā)工作
Spring Data,是為數(shù)據(jù)訪問提供熟悉且一致的基于Spring的編程模型,同時仍然保留底層數(shù)據(jù)存儲的特殊特性。
它是對于數(shù)據(jù)訪問技術(shù),關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫,map-reduce框架和基于云的數(shù)據(jù)服務(wù)變得容易。Spring Data是一個總括項(xiàng)目,其中包含很多特定于數(shù)據(jù)庫相關(guān)的子項(xiàng)目。

首先,先帶大家看一下本篇文章的大致介紹。
沒目錄怎么知道這篇到底有多少干貨呢?
- Spring Data是什么
- Spring Data能干什么
- Spring Data的第一個HelloWorld程序
- 通過名字來確定方法
- 通過注解的形式來實(shí)現(xiàn)查詢
- 寫本地的SQL查詢
- 增刪改的玩法
- 使用框架中提供的增刪改查的方法
- 分頁和排序
- JpaRepository的使用
是不是很清晰呢,現(xiàn)在開始進(jìn)入正文,一個一個來:
Spring Data是什么
我們傳統(tǒng)的開發(fā)中,我們的整個DAO層的代碼上都是相對來說,都是比較復(fù)雜的,在這種情況下,Spring團(tuán)隊(duì)就考慮到一個問題,能不能開發(fā)一個框架,這個框架能夠最大限度的減少DAO層的開發(fā)呢?
Spring Data就是為了簡化DAO層操作的一個框架
傳統(tǒng)的增刪改查在我們的Spring Data中已經(jīng)實(shí)現(xiàn)了,也就是說大部分的DAO層操作部分不用寫了,僅僅只是需要編寫復(fù)雜的業(yè)務(wù)的調(diào)用就可以啦

寫的這部分的代碼,是需要寫接口的聲明就可以啦,不用寫實(shí)現(xiàn),這個實(shí)現(xiàn)是自動實(shí)現(xiàn)的
Spring Data能干什么
主要用途:
- 傳統(tǒng)的增刪改查
- 排序
- 分頁
- 排序后分頁
即使你需要寫DAO,也只是寫聲明就可以啦,不用寫實(shí)現(xiàn)
Spring Data的第一個HelloWorld程序(JPA、Hibernate、Spring、SpringMVC、Spring Data)
導(dǎo)包

編寫配置文件
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- 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.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/data/jpa
- http://www.springframework.org/schema/data/jpa/spring-jpa-1.2.xsd">
- <!--引入Properties文件-->
- <context:property-placeholder location="classpath:config/db.properties"/>
- <!--配置c3p0的連接池-->
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="driverClass" value="${driverClass}"></property>
- <property name="jdbcUrl" value="${url}"></property>
- <property name="user" value="${user}"></property>
- <property name="password" value="${password}"></property>
- <property name="acquireIncrement" value="${acquireIncrement}"></property>
- <property name="maxPoolSize" value="${maxPoolSize}"></property>
- <property name="minPoolSize" value="${minPoolSize}"></property>
- <property name="maxStatements" value="${maxStatements}"></property>
- </bean>
- <!--配置JPA實(shí)現(xiàn)產(chǎn)品的適配器-->
- <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
- </bean>
- <!--配置EntityManager對象-->
- <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
- <!--注入數(shù)據(jù)源-->
- <property name="dataSource" ref="dataSource"></property>
- <!--掃描entity包的-->
- <property name="packagesToScan" value="com.qy.helloworld"></property>
- <!--注入JPA實(shí)現(xiàn)產(chǎn)品的適配器-->
- <property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>
- <!--配置的是Hibernate的其他配置 除了連接數(shù)據(jù)庫4大要素之外的其余配置-->
- <property name="jpaProperties">
- <props>
- <!--是否自動創(chuàng)建表 -->
- <prop key="hibernate.hbm2ddl.auto">update</prop>
- <!--配置是否展示SQL-->
- <prop key="hibernate.show_sql">true</prop>
- <!--是否格式化SQL-->
- <prop key="hibernate.format_sql">true</prop>
- <!--連接數(shù)據(jù)庫的方言-->
- <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
- </props>
- </property>
- </bean>
- <!--配置事務(wù)環(huán)境-->
- <bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
- <!--注入dataSource-->
- <property name="dataSource" ref="dataSource"></property>
- <!--注入entityManagerFactory對象-->
- <property name="entityManagerFactory" ref="entityManagerFactory"></property>
- </bean>
- <!--使用事務(wù)-->
- <tx:annotation-driven transaction-manager="jpaTransactionManager"/>
- <!--配置AOP的自動代理-->
- <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- <!--配置Spring的包掃描-->
- <context:component-scan base-package="com.qy.helloworld"></context:component-scan>
- <!--Spring data的包的掃描 這里的掃描掃描的是DAO層所在的位置-->
- <jpa:repositories base-package="com.qy.helloworld" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="jpaTransactionManager"></jpa:repositories>
- </beans>
編寫實(shí)體類和映射
- @Entity
- @Table(name="t_user")
- public class User {
- @Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
- private int userId;
- private String userName;
- private String password;
- }
編寫Repository類
- public interface UserRepository extends Repository<User,Integer>{
- /**
- * 這個的意思是通過id找用戶
- * @Title: getByUserId
- * @Description: TODO
- * @param: @param userId
- * @param: @return
- * @return: User
- * @throws
- */
- public User getByUserId(int userId);
- }
測試
- ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
- //獲取DAO的對象
- UserRepository userRepository=applicationContext.getBean(UserRepository.class);
- User users=userRepository.findByUserId(1);
- }
通過名字來確定方法
代碼演示:
舉例如下:
- public interface UserRepository extends Repository<User,Integer>{
- /**
- * 這個的意思是通過id找用戶
- * @Title: getByUserId
- * @Description: TODO
- * @param: @param userId
- * @param: @return
- * @return: User
- * @throws
- */
- public User getByUserId(int userId);
- /**
- * 記住查詢的開頭只能是 get 或者 find 開頭 By:通過什么查詢
- * @Title: findByUserId
- * @Description: TODO
- * @param: @param userId
- * @param: @return
- * @return: User
- * @throws
- */
- public User findByUserId(int userId);
- /**
- * 通過用戶名的模糊查詢
- * @Title: findByUserNameLike
- * @Description: TODO
- * @param: @param userName
- * @param: @return
- * @return: List<User>
- * @throws
- */
- public List<User> findByUserNameLike(String userName);
- /**
- * 通過用戶名和密碼的Like來進(jìn)行查詢
- * @Title: findByUserNameLikeAndPasswordLike
- * @Description: TODO
- * @param: @param userName
- * @param: @return
- * @return: List<User>
- * @throws
- */
- public List<User> findByUserNameLikeAndPasswordLike(String userName,String password);
- /**
- * 用戶名和密碼like 然后id小于一個范圍
- * @Title: findByUserNameLikeAndPasswordLikeAndUserIdLessThan
- * @Description: TODO
- * @param: @param userName
- * @param: @param password
- * @param: @param userId
- * @param: @return
- * @return: List<User>
- * @throws
- */
- public List<User> findByUserNameLikeAndPasswordLikeAndUserIdLessThan(String userName,String password,int userId);
- }
注意:一般情況下不會通過名字直接來寫相應(yīng)的方法,因?yàn)槿绻麠l件過多那么這個時候我們就存在名字特別長的問題
通過注解的模式來實(shí)現(xiàn)查詢
代碼演示:
舉例如下:
- /**
- * 查詢所有 沒有條件直接查詢
- * @Title: findUserAll
- * @Description: TODO
- * @param: @return
- * @return: List<User>
- * @throws
- */
- @Query("from User")
- public List<User> findUserAll();
- /**
- * 通過id來查找數(shù)據(jù) 參數(shù)直接拼接到后面
- * @Title: findUserById
- * @Description: TODO
- * @param: @param userId
- * @param: @return
- * @return: List<User>
- * @throws
- */
- @Query("from User u where u.userId<3")
- public List<User> findUserById();
- /**
- * 通過id查詢存在占位符的情況
- * @Title: findUserById1
- * @Description: TODO
- * @param: @param userId
- * @param: @return
- * @return: List<User>
- * @throws
- */
- @Query("from User u where u.userId<?")
- public List<User> findUserById1(int userId);
- /**
- * 多條件的查詢 可以指定當(dāng)前的參數(shù)映射的這個位置
- * @Title: getUserByNameAndId
- * @Description: TODO
- * @param: @param userName
- * @param: @param userId
- * @param: @return
- * @return: User
- * @throws
- */
- @Query("from User u where u.userId=?2 and u.userName=?1")
- public User getUserByNameAndId(String userName,int userId);
- /**
- * 模糊查詢的時候動態(tài)拼接上 %的問題
- * @Title: findUserByLike1
- * @Description: TODO
- * @param: @param userName
- * @param: @return
- * @return: List<User>
- * @throws
- */
- @Query("from User u where u.userName like concat ('%',?,'%')")
- public List<User> findUserByLike1(String userName);
寫本地的SQL 查詢
代碼演示:
舉例如下:
- /**
- * 通過
- * @Title: findUserAll11
- * @Description: TODO
- * @param: @return
- * @return: List<User>
- * @throws
- */
- @Query(nativeQuery=true,value="select * from t_user")
- public List<User> findUserAll11();
增刪改的玩法
代碼演示:
添加業(yè)務(wù)邏輯 增加事務(wù)環(huán)境:
- @Service
- @Transactional //提供一個事務(wù)的環(huán)境
- public class UserService {
- @Autowired
- private UserRepository userRepository=null;
- /**
- * 數(shù)據(jù)的更新
- * @Title: update
- * @Description: TODO
- * @param: @param userName
- * @param: @param password
- * @param: @param userId
- * @return: void
- * @throws
- */
- public void update(String userName,String password,int userId){
- userRepository.update(userName, password, userId);
- }
- public void delete(int userId){
- userRepository.delete(userId);
- }
- public void insert(String userName,String password){
- userRepository.insert(userName, password);
- }
- }
編寫repository的對象:
- public interface UserRepository extends Repository<User,Integer>{
- /**
- * 實(shí)現(xiàn)增刪改的方法
- * @Title: add
- * @Description: TODO
- * @param: @param userName
- * @param: @param password
- * @return: void
- * @throws
- */
- @Modifying //這個注解的作用表示的是更新數(shù)據(jù)
- @Query("update User u set u.userName=?,u.password=? where u.userId=?")
- public void update(String userName,String password,int userId);
- /**
- * 更新數(shù)據(jù)
- * @Title: delete
- * @Description: TODO
- * @param: @param userId
- * @return: void
- * @throws
- */
- @Modifying //這個注解的作用表示的是更新數(shù)據(jù)
- @Query("delete User u where u.userId=?")
- public void delete(int userId);
- /**
- * 添加數(shù)據(jù)
- * @Title: insert
- * @Description: TODO
- * @param: @param userName
- * @param: @param password
- * @return: void
- * @throws
- */
- @Modifying //這個注解的作用表示的是更新數(shù)據(jù)
- @Query(nativeQuery=true,value="insert into t_user(userName,password) values(?,?)")
- public void insert(String userName,String password);
- }
測試:
- @Test
- public void testHelloWorld() throws Exception {
- ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
- //獲取DAO的對象
- UserService userService=applicationContext.getBean(UserService.class);
- userService.insert("小羽","做程序的");
使用框架中提供的增刪改查的方法
代碼演示:
提供的是Repository:
- public interface UserRepository extends CrudRepository<User,Integer>{
分頁和排序
代碼演示:
提供的Repository:
- public interface UserRepository extends PagingAndSortingRepository<User,Integer>{
測試:
- public class Test001 {
- @Test
- public void testPaging() throws Exception {
- ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
- //獲取DAO的對象
- UserRepository userRepository=applicationContext.getBean(UserRepository.class);
- /**
- * 第一個參數(shù):當(dāng)前的頁的頁數(shù)是多少 頁數(shù)是從0開始的 第二頁:2-1
- * 第二個參數(shù):表示的是每一頁條目數(shù)
- */
- Page<User> pages=userRepository.findAll(new PageRequest(2-1,2));
- System.out.println("查詢到的數(shù)據(jù):"+pages.getContent());
- System.out.println("數(shù)據(jù)的條目數(shù):"+pages.getSize());
- System.out.println("頁數(shù):"+pages.getNumber());
- System.out.println("數(shù)據(jù)條目的總數(shù):"+pages.getTotalElements());
- System.out.println("一共的頁數(shù):"+pages.getTotalPages());
- System.out.println("排序的規(guī)則:"+pages.getSort());
- }
- /**
- * 排序
- * @Title: testSort
- * @Description: TODO
- * @param: @throws Exception
- * @return: void
- * @throws
- */
- @Test
- public void testSort() throws Exception {
- ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
- //獲取DAO的對象
- UserRepository userRepository=applicationContext.getBean(UserRepository.class);
- /**
- * 排序
- * 第一個參數(shù):升序或者降序 Direction.ASC/DESC
- * 第二個參數(shù): 排序的這個列
- */
- List<User> users=(List<User>) userRepository.findAll(new Sort(Direction.DESC,"userId"));
- System.out.println(users);
- }
- /**
- * 排序后分頁
- * @Title: testSortAndPaging
- * @Description: TODO
- * @param: @throws Exception
- * @return: void
- * @throws
- */
- @Test
- public void testSortAndPaging() throws Exception {
- ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
- //獲取DAO的對象
- UserRepository userRepository=applicationContext.getBean(UserRepository.class);
- Page<User> pages=userRepository.findAll(new PageRequest(2-1,2,new Sort(Direction.DESC,"userId")));
- System.out.println(pages.getContent());
- }
JpaRepository的使用
代碼演示:
提供的repository:
- public interface UserRepository extends JpaRepository<User,Integer>{
測試:
- public class Test001 {
- @Test
- public void testPaging() throws Exception {
- ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
- //獲取DAO的對象
- UserRepository userRepository=applicationContext.getBean(UserRepository.class);
- // long count=userRepository.count();
- // User user=userRepository.findOne(15);
- // user.setUserName("小羽");
- //保存或者更新數(shù)據(jù)
- // userRepository.saveAndFlush(user);
- List<User> users=userRepository.findAll();
- //批處理
- userRepository.deleteInBatch(users);
- //System.out.println("統(tǒng)計:"+count);
- }
- }
結(jié)語
Spring Data是我們開發(fā)中離不開的經(jīng)常用到的技術(shù),其涉及的技術(shù)和知識面其實(shí)遠(yuǎn)不止上面列出的這些。
后續(xù)淺羽會繼續(xù)更新關(guān)于Spring Data的開發(fā)知識,只希望能對大家有所幫助,謝謝大家的支持!