看Spring Data如何简化数据操作
Spring Data 概述
Spring Data
用于简化数据库访问,支持NoSQL 和 关系数据存储,其主要目标是使数据库的访问变得方便快捷。
SpringData 项目所支持 NoSQL 存储:
MongoDB (文档数据库)
Neo4j(图形数据库)
Redis(键/值存储)
Hbase(列族数据库)
SpringData 项目所支持的关系数据存储技术:
JDBC
JPA
Spring Data JPA
JPA Spring Data : 致力于减少数据访问层 (DAO) 的开发量. 开发者唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成!
开发步骤
配置 Spring 整合 JPA
在 Spring 配置文件中配置 Spring Data,让 Spring 为声明的接口创建代理对象,配置了 \<jpa:repositories> 后,Spring 初始化容器时将会扫描 base-package 指定的包目录及其子目录,为继承 Repository 或其子接口的接口创建代理对象,并将代理对象注册为 Spring Bean,业务层便可以通过 Spring 自动封装的特性来直接使用该对象。
声明持久层的接口,该接口继承 Repository,Repository 是一个标记型接口,它不包含任何方法,如必要,Spring Data 可实现 Repository 其他子接口,其中定义了一些常用的增删改查,以及分页相关的方法。
在接口中声明需要的方法,Spring Data 将根据给定的策略来为其生成实现代码。
搭建环境
导包:
antlr-2.7.7.jar
c3p0-0.9.2.1.jar
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.3.jar
dom4j-1.6.1.jar
hamcrest-core-1.3.jar
hibernate-c3p0-4.2.4.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
hibernate-core-4.2.4.Final.jar
hibernate-entitymanager-4.2.4.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
javassist-3.15.0-GA.jar
jboss-logging-3.1.0.GA.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
junit-4.12.jar
mchange-commons-java-0.2.3.4.jar
mysql-connector-java-5.1.7-bin.jar
slf4j-api-1.6.1.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-data-commons-1.6.2.RELEASE.jar
spring-data-jpa-1.4.2.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
applicationContext.xml
<?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:context="http://www.springframework.org/schema/context" 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.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:component-scan base-package="com.kernel.spring.data"/> <!--配置数据源--> <context:property-placeholder location="classpath:db.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--配置JPA的EntityManagerFactory--> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> <property name="packagesToScan" value="com.kernel.spring.data"/> <property name="jpaProperties"> <props> <!--生成的数据表的映射策略--> <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop> <!--生成的数据表的列的映射策略--> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <!--配置事务管理器--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!--配置支持注解的事务--> <tx:annotation-driven transaction-manager="transactionManager"/> <!--配置Spring Data--> <jpa:repositories base-package="com.kernel.spring.data" entity-manager-factory-ref="entityManagerFactory"/> </beans>
Repository 接口
Repository 接口是 Spring Data 的一个核心接口,不提供任何方法,只要遵循接口方法定义规范,就无需写实现类,与继承 Repository 接口等价的一种方式,就是在持久层接口上使用 @RepositoryDefinition 注解,并为其指定domainClass 和 idClass 属性。
Repository 的子接口
Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类。
CrudRepository: 继承 Repository,实现了一组 CRUD 相关的方法 。
PagingAndSortingRepository: 继承 CrudRepository,实现了一组分页排序相关的方法 。
JpaRepository: 继承 PagingAndSortingRepository,实现一组 JPA 规范相关的方法 。
自定义的 XxxxRepository 需要继承 JpaRepository,这样的 XxxxRepository 接口就具备了通用的数据访问控制层的能力。
JpaSpecificationExecutor: 不属于Repository体系,实现一组 JPA Criteria 查询相关的方法 。
Spring Data 方法定义规范
简单条件查询,查询某一个实体或者集合,查询方法以 get、find、read 开头,涉及条件查询时,条件的属性用关键字连接,条件属性以首字母大写。
例如
public interface PersonRepository extends Repository<Person, Integer> { Person getByLastName(String lastName); List<Person> getByLastNameStartingWithAndIdLessThan(String lastName, Integer id); List<Person> getByLastNameEndingWithAndIdLessThan(String lastName, Integer id); List<Person> getByEmailInAndAgeLessThan(List list, Integer id); List<Person> getByAddress_IdGreaterThan(Integer id); }
Spring Data 支持的关键字
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstname,findByFirstnameIs,findByFirstnameEquals | … where x.firstname = 1? |
Betwee | findByStartDateBetween | … where x.startDate between 1? and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
LessThanEqual | findByAgeLessThanEqual | … where x.age <= ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1(parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1 (parameter bound with prepended %) |
Containing | findByFirstnameContaining | … where x.firstname like ?1(parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection<Age> ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection<Age> age) | … where x.age not in ?1 |
True | findByActiveTrue() | … where x.active = true |
False | findByActiveFalse() | … where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase | … where UPPER(x.firstame) = UPPER(?1) |
@Query 注解
这种查询可以声明在 Repository 方法中,摆脱像命名查询那样的约束,将查询直接在相应的接口方法中声明,结构更为清晰,这是 Spring Data 的特有实现。
索引参数:
索引值从1开始,查询中 ?x 的个数需要与方法形参个数相等,并且顺序也要一致。
@Query("SELECT p FROM Person p WHERE p.lastName = ?1 and p.age = ?2") Person getByLastNameAndAge(String lastName, int age);
命名参数:
可以定义好参数名,赋值值采用 @Param(参数名),而不用管顺序。
@Query("SELECT p FROM Person p WHERE p.lastName = :lastName and p.id = :id") Person getByLastNameAndId(@Param("id")int id, @Param("lastName")String lastName);
本地查询:
可以使用 @Query 执行本地查询,只要设置 nativeQuery 为 true。
@Query(value = "SELECT COUNT (id) FROM jpa_persons", nativeQuery = true) long getTotalCount();
@Modifying 注解和事务
@Query 与 @Modifying 这两个注解一起使用,可以执行 UPDATE、DELETE 操作。
注意,UPDATE、DELETE 需要使用事务,因此需要定义在 Service 层。
事务:
Spring Data 提供了默认的事务处理方式,即所有的查询均为只读事务。
对于自定义的方法,如需改变 Spring Data 提供的事务方式,可以在方法上添加 @Transactional 注解。
进行多个 Repository 操作时,也应该使它们在同一个事务中处理,按照分层架构的思想,这部分属于业务逻辑层,因此,需要在 Service 层实现对多个 Repository 的调用,并在相应的方法上声明事务。
CrudRepository 接口
CrudRepository 接口提供了最基本的对实体类的添删改查操作
T save(T entity) 保存单个实体
Iterable<T> save(Iterable<? extends T> entities) 保存集合
T findOne(ID id) 根据id查找实体
boolean exists(ID id) 根据id判断实体是否存在
Iterable<T> findAll() 查询所有实体,不用或慎用
long count() 查询实体数量
void delete(ID id) 根据Id删除实体
void delete(T entity) 删除一个实体
void delete(Iterable<? extends T> entities) 删除一个实体的集合
void deleteAll() 删除所有实体,不用或慎用
PagingAndSortingRepository 接口
该接口提供了分页与排序功能
Iterable<T> findAll(Sort sort) 排序
Page<T> findAll(Pageable pageable) 分页查询(含排序功能)
@Test public void testPagingAndSortingRespository(){ int pageNo = 3; int pageSize = 5; Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id"); Sort.Order order1 = new Sort.Order(Sort.Direction.ASC, "email"); Sort sort = new Sort(order,order1); PageRequest pageable = new PageRequest(pageNo, pageSize, sort); Page<Person> page = personRepository.findAll(pageable); System.out.println(page.getNumberOfElements()); System.out.println(page.getContent()); }
JpaRepository 接口
该接口提供了JPA的相关功能
List<T> findAll() 查找所有实体
List<T> findAll(Sort sort) 排序、查找所有实体
List<T> save(Iterable<? extends T> entities) 保存集合
void flush() 执行缓存与数据库同步
T saveAndFlush(T entity) 强制执行持久化
void deleteInBatch(Iterable<T> entities) 删除一个实体集合
JpaSpecificationExecutor 接口
不属于Repository体系,实现一组 JPA Criteria 查询相关的方法
Specification:封装 JPA Criteria 查询条件。通常使用匿名内部类的方式来创建该接口的对象
@Test public void testJpaSpecificationExecutor(){ int pageNo = 3; int pageSize = 5; PageRequest pageable = new PageRequest(pageNo, pageSize); Specification<Person> specification = new Specification<Person>() { /** * @param root 代表查询的实体类 * @param criteriaQuery 可以从中得到root对象,即告知 JPA Criteria 查询哪个实体类, * 还可以添加查询条件,还可以结合EntityManager对象得到最终查询的 TypedQuery * @param criteriaBuilder 用于创建criteria工厂 * @return Predicate类型,代表一个查询条件 */ @Override public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { Predicate predicate = criteriaBuilder.ge(root.get("id"),5); return predicate; } }; Page<Person> page = personRepository.findAll(specification, pageable); System.out.println(page.getNumberOfElements()); System.out.println(page.getContent()); }
自定义 Repository 方法
为某一个 Repository 上添加自定义方法
创建一个 XXXDAO 接口,声明接口方法。
创建一个 XXXRepository 接口,并继承 XXXDAO 接口。
提供 XXXRepository 的实现类 XXXRepositoryImpl,并实现 XXXDAO 定义的接口方法。
实际上在使用 XXXRepository 的自定义方法时会调用 XXXRepositoryImpl 中的实现。
为所有的 Repository 都添加自实现的方法
创建一个 XXXRepository 接口,需要继承 创建一个 Repository 接口。
提供 XXXRepository 的实现类 XXXRepositoryImpl,且继承 SimpleJpaRepository,并提供方法的实现。
定义 JpaRepositoryFactoryBean 的实现类,使其生成 XXXRepository 的接口实现类的对象。
修改 \<jpa:repositories/> 节点的 factory-class 属性指向 JpaRepositoryFactoryBean 的实现类的全类名。
注意:
全局的扩展实现类不要用 Imp 作为后缀名,
或者为全局扩展接口添加 @NoRepositoryBean注解告知 SpringData 不要把其作为 Repository。
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2o6lnn9to9mo4
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
kubernetes service 和 ingress
一 总述 1 service 作用 POD 中运行的容器存在动态、弹性的变化(容器的重启IP地址会变化),因此便产生了service,其资源为此类POD对象提供一个固定、统一的访问接口及负载均衡能力,并借助DNS系统的服务发现功能,解决客户端发现容器难得问题 service 和POD 对象的IP地址在集群内部可达,但集群外部用户无法接入服务,解决的思路有:1 在POD上做端口暴露(hostPort)2 在工作节点上公用网络名称空间(hostNetwork)3 使用service 的NodePort 或 loadbalancer (service 依赖于 DNS资源服务)4 ingress七层负载均衡和反向代理资源 2 service资源及实现模型 1 service 概述 1 service是微服务的一种实现,事实上其是一种抽象:通过关注定义出多个POD对象组合而成的逻辑集合,以及访问这组POD的策略,service关联POD 需要标签选择器完成,其基于标签选择器将一组POD定义成一个逻辑集合,并通过自己的IP地址和端口调度代理请求至后端POD之上。 2 service 对象的IP地址...
- 下一篇
干掉一堆mysql数据库,仅需这样一个shell脚本
一大早就被电话吵醒了,云某项目数据库全挂了,启动不了(睡得太死,没听到报警短信),吓得不轻啊! 电话中说所有mysql数据库主库都启动不了,但从库正常,怀疑是主库去连其它阿里云的主库了。这些数据库,以前是从阿里云迁移到idc机房的,因此他有这个判断。 赶紧打开电脑,连***,登录其中一个数据库服务器,试着执行如下命令启动mysql服务 [root@bbsmysql121 backup]#mysqld_safe –user=mysql & 启动失败,又换一台数据库服务器尝试,还是失败。考虑到所有的数据库都不能启动,因此可以初步判定,可能是数据库宿主机的问题导致的。 数据库的底层设计是两台物理节点虚拟化,外加一台物理机做备份。其中一台物理机的虚拟机全部做mysql主库,另一台物理机的虚拟机做mysql从库。 先放弃在虚拟机进行故障排查,赶紧登录宿主机系统。接下来,从两个方面排查问题所在。 ü 虚拟化后台管理系统 发现存储被塞满了,问题很严重。 ü ssh登录宿主系统debian [6885005.756183] Buffer I/O error on dev dm-16, l...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS关闭SELinux安全模块
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2整合Redis,开启缓存,提高访问速度
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程