文档章节

spring学习:spring data jpa

architect刘源源
 architect刘源源
发布于 2018/01/15 13:07
字数 1474
阅读 4
收藏 1

工程改进

    在前一篇文章中,我们讨论过对工程的改进。在最开始的思路里,我们是定义了ContactService接口,在具体的ContactServiceImpl里直接引用sessionFactory或者EntityManager来操作数据。在这种情况下,我们的实际业务逻辑却直接和数据操作部分耦合起来了。于是,为了使得这部分不是紧密耦合的。我们定义了dao包,将真正数据访问的部分放在dao的实现里。

    另外,考虑到对数据的基本增删查改算是最常用的操作。几乎每个对象都需要,我们完全可以定义一个通用的给其他dao实现来集成。因为要足够通用,我们采用泛型的参数接口。于是就得出了一个如下图的设计思路:

     在这种实现里,我们定义了dao的抽象接口。理论上它可以进行CRUD操作的数据可以是继承自Object的任何对象。然后我们需要继承dao接口来定义自己的特定dao操作部分。而针对dao本身这些基础的crud操作就都由AbstractHbnDao实现了。我们定义自己的实现时只需要继承AbstractHbnDao,然后实现自定义的那部分接口就可以了 。

    这种方式带来了不少的便利。当然,也带来了一个可以改进的地方。既然这个dao是用来针对通用的对象操作的。而且AbstractHbnDao也是定义的一个通用操作。那么可不可以直接将它们实现好作为一个通用的类库呢?这样以后我们就连这部分的定义都省了。真是基于这个观点,我们找到了spring data jpa。

 

引入spring data jpa

    spring data jpa是一个通用的DAO框架。它除了支持基础的crud操作之外,还分页、排序和批处理操作。我们原来很多需要手工定义的dao类它都通过动态代理生成了。

    spring data jpa的类结构图如下:

 

     我们在工程中使用它们就比较简单了。首先定义一个自定义的dao接口。比如本例中的ContactDao:

Java代码  收藏代码

  1. package com.yunzero.dao;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.data.repository.CrudRepository;  
  6.   
  7. import com.yunzero.model.Contact;  
  8.   
  9. public interface ContactDao extends CrudRepository<Contact, Long> {  
  10.       
  11.     List<Contact> findByEmailLike(String email);  
  12. }  

     在这里我们可以看到,我们自定义的方法findByEmailLike。按照以往的思路,既然这是我们定义的方法,总该要我们自己去实现它吧?可是在这里,居然不用自己去实现它。我们看后续的代码:

  ContactService:

Java代码  收藏代码

  1. package com.yunzero.service;  
  2.   
  3. import java.util.List;  
  4.   
  5. import com.yunzero.model.Contact;  
  6.   
  7. public interface ContactService {  
  8.   
  9.     void createContact(Contact contact);  
  10.   
  11.     List<Contact> getContacts();  
  12.       
  13.     List<Contact> getContactsByEmail(String email);  
  14.   
  15.     Contact getContact(Long id);  
  16.       
  17.     void updateContact(Contact contact);  
  18.   
  19.     void deleteContact(Long id);  
  20. }  

   真正重点的是ContactServiceImpl:

Java代码  收藏代码

  1. package com.yunzero.service.impl;  
  2.   
  3. import static org.springframework.util.Assert.notNull;  
  4.   
  5. import java.util.ArrayList;  
  6. import java.util.Iterator;  
  7. import java.util.List;  
  8.   
  9. import javax.inject.Inject;  
  10.   
  11. import org.springframework.stereotype.Service;  
  12. import org.springframework.transaction.annotation.Transactional;  
  13.   
  14. import com.yunzero.dao.ContactDao;  
  15. import com.yunzero.model.Contact;  
  16. import com.yunzero.service.ContactService;  
  17.   
  18. @Service  
  19. @Transactional  
  20. public class ContactServiceImpl implements ContactService {  
  21.     @Inject private ContactDao contactDao;  
  22.   
  23.     @Override  
  24.     public void createContact(Contact contact) {  
  25.         notNull(contact, "contact can't be null");  
  26.         contactDao.save(contact);  
  27.     }  
  28.   
  29.     @Override  
  30.     public List<Contact> getContacts() {  
  31.         Iterable<Contact> iterable = contactDao.findAll();  
  32.         Iterator<Contact> iterator = iterable.iterator();  
  33.         List<Contact> contacts = new ArrayList<Contact>();  
  34.         while (iterator.hasNext()) {  
  35.             contacts.add(iterator.next());  
  36.         }  
  37.         return contacts;  
  38.     }  
  39.       
  40.     @Override  
  41.     public List<Contact> getContactsByEmail(String email) {  
  42.         notNull(email, "email can't be null");  
  43.         return contactDao.findByEmailLike("%" + email + "%");  
  44.     }  
  45.   
  46.     @Override  
  47.     public Contact getContact(Long id) {  
  48.         notNull(id, "id can't be null");  
  49.         return contactDao.findOne(id);  
  50.     }  
  51.   
  52.     @Override  
  53.     public void updateContact(Contact contact) {  
  54.         notNull(contact, "contact can't be null");  
  55.         contactDao.save(contact);  
  56.     }  
  57.   
  58.     @Override  
  59.     public void deleteContact(Long id) {  
  60.         notNull(id, "id can't be null");  
  61.         contactDao.delete(id);  
  62.     }  
  63. }  

     这里最玄乎的就是contactDao有了save, delete等方法了。而实际上ContactDao继承的不是接口吗?而且更猛的是,我在ContactDao里定义的方法findByEmailLike没有定义实现居然可以拿来直接用!这一切看起来像魔法一样,实在是太不可思议了。

    实际上,这一切就是spring data jpa的动态代理方法带来的好处。我们定义的方法只要按照它定义的规则来命名,它就可以通过反射将名字和各种操作方法和映射起来。有点convention over configuration的感觉哈。对于具体spring data jpa是怎么实现这些的,这里不再赘述,在后面的文章中会详细讨论。

 

配置

    上面就是所有的代码了。除了前面代码部分,还要一个需要注意的就是配置。这里一个典型的配置如下:

Java代码  收藏代码

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.     xmlns:c="http://www.springframework.org/schema/c"  
  5.     xmlns:context="http://www.springframework.org/schema/context"  
  6.     xmlns:jee="http://www.springframework.org/schema/jee"  
  7.     xmlns:jpa="http://www.springframework.org/schema/data/jpa"  
  8.     xmlns:p="http://www.springframework.org/schema/p"  
  9.     xmlns:tx="http://www.springframework.org/schema/tx"  
  10.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  11.     xsi:schemaLocation="  
  12.         http://www.springframework.org/schema/beans  
  13.         http://www.springframework.org/schema/beans/spring-beans-4.1.xsd  
  14.         http://www.springframework.org/schema/context  
  15.         http://www.springframework.org/schema/context/spring-context-4.1.xsd  
  16.         http://www.springframework.org/schema/data/jpa  
  17.         http://www.springframework.org/schema/data/jpa/spring-jpa-1.8.xsd  
  18.         http://www.springframework.org/schema/jee  
  19.         http://www.springframework.org/schema/jee/spring-jee-4.1.xsd  
  20.         http://www.springframework.org/schema/tx  
  21.         http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">  
  22.       
  23.     <context:property-placeholder location="classpath:/environment.properties" />  
  24.       
  25.     <bean id="dataSource"  
  26.         class="org.apache.commons.dbcp2.BasicDataSource"  
  27.         destroy-method="close"  
  28.         p:driverClassName="${dataSource.driverClassName}"  
  29.         p:url="${dataSource.url}"  
  30.         p:username="${dataSource.username}"  
  31.         p:password="${dataSource.password}" />  
  32.   
  33.     <bean id="entityManagerFactory"  
  34.         class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"  
  35.         p:dataSource-ref="dataSource"  
  36.         p:packagesToScan="com.yunzero.model">  
  37.           
  38.         <property name="persistenceProvider">  
  39.             <bean class="org.hibernate.jpa.HibernatePersistenceProvider" />  
  40.         </property>  
  41.         <property name="jpaProperties">  
  42.             <props>  
  43.                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>  
  44.                 <prop key="hibernate.show_sql">false</prop>  
  45.             </props>  
  46.         </property>  
  47.     </bean>  
  48.       
  49.     <bean id="transactionManager"  
  50.         class="org.springframework.orm.jpa.JpaTransactionManager"  
  51.         p:entityManagerFactory-ref="entityManagerFactory" />  
  52.       
  53.     <tx:annotation-driven />  
  54.       
  55.     <jpa:repositories base-package="com.yunzero.dao" />  
  56.     <context:component-scan base-package="com.yunzero.service.impl" />  
  57. </beans>  

     看起来和前面的配置没什么差别。唯一的一点就是引入了jpa的命名空间,并引入了这么一个配置。<jpa:repositories base-package="com.yunzero.dao" />

   当然,在我们依赖的包里也需要引入spring-data-jpa,如下是一个典型的引用内容:

Java代码  收藏代码

  1. <dependency>  
  2.         <groupId>org.springframework.data</groupId>  
  3.         <artifactId>spring-data-jpa</artifactId>  
  4.     <version>1.8.0.RELEASE</version>  
  5. </dependency>  

  就只要这么几步,整个数据操作的部分就完成了。详细的实现可以参考后面的附件。

     

总结

     spring data jpa是对dao方式操作数据的进一步优化。它带来的不仅仅是一个抽象的通用数据访问接口,更多的是一个按照命名规范自动生成的数据访问实现。这些玄妙之处值得后续好好学习。

© 著作权归作者所有

architect刘源源

architect刘源源

粉丝 167
博文 555
码字总数 935372
作品 0
浦东
程序员
私信 提问
解决spring jpa中配置文件报'jpa:repositories'的问题

一、问题描述 使用spring jpa,报no declaration can be found for element 'jpa:repositories'错误的解决方案 Multiple annotations found at this line: - cvc-complex-type.2.4.c: The mat......

cloud-coder
2014/04/17
5K
1
下载最新springside jpa schema问题

xsi:schemaLocation="http://www.springframework.org/schema/data/jpa/spring-jpa-1.1.xsd“ 出现Description Resource Path Location Type Referenced file contains errors (http://www.s......

kennylixi
2012/08/09
593
3
(入门帖)使用 Spring Data JPA 简化 JPA 开发

本文主要讲述 Spring Data JPA,但是为了不至于给 JPA 和 Spring 的初学者造成较大的学习曲线,我们首先从 JPA 开始,简单介绍一个 JPA 示例;接着重构该示例,并引入 Spring 框架,这两部分...

阿莱倪士
2014/01/09
638
0
Spring Boot [组件学习-Spring Data JPA]

导读: 在上篇文章中对Spring MVC常用的一些注解做了简要的说明,在这篇文章中主要对Spring Data JPA 做一个简要的说明,并附有一个简单的例子,可以体会到Spring Data JPA 的强大之处。 Sp...

yangrd
2018/08/27
0
0
Spring mvc 创建完项目测试的时候前台404,后台没有错误信息这是咋了

前天遇到一个问题,springmvc创建的项目测试的时候前台404,后台没有错误输出,奇了怪了...... 这是WEB-INF下的xml文件 SpringMVC05 index.html index.htm index.jsp default.html default....

好吧我输了
2018/06/19
230
3

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
538
14
SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
19
0
排序––快速排序(二)

根据排序––快速排序(一)的描述,现准备写一个快速排序的主体框架: 1、首先需要设置一个枢轴元素即setPivot(int i); 2、然后需要与枢轴元素进行比较即int comparePivot(int j); 3、最后...

FAT_mt
昨天
4
0
mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
昨天
12
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
昨天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部