一. 引入Docker
二. Spring Data JPA
1.Spring Data JPA
是Spring Data的一个子项目,它通过提供基于JPA的Repository极大地减少了JPA作为数据访问方案的代码量。JPA的主要实现有Hibernate,EclipseLink和OpenJPA等
2.定义数据访问层
@Entity
public class Person{
@Id
@GeneratedValue
private int id;
private String name;
private Integer age;
private String address;
//set get
}
public interface PersonRepository extends JpaRepository<Person,Long>{
//定义数据访问操作的方法
}
3.配置使用Spring Data JPA
在spring环境中,使用Spring Data JPA可通过@EnableJpaRepositories来注解开启Spring Data JPA的支持,@EnableJpaRepositories接受的value参数用来扫描数据访问层所在包下的数据访问接口定义。
@Configuration
@EnableJpaRepositories("com.shm.dao")
public class JpaConfiguration{
@Bean
public EntityManagerFactory entityManagerFactory(){
//...
}
//还需要配置DataSource,PlatformTransactionManager等相关必须bean
}
4.定义查询方法
4.1 根据属性名查询
public interface PersonRepository extends JpaRepository<Person,Long>{
//定义数据访问操作的方法
/**
*通过名字相等查询,参数为name
*相当于JPQL:select p from Person p where p.name=?1
*/
List<Person> findByName(String anme);
/**
*通过名字like查询,参数为name
*相当于JPQL:select p from Person p where p.name like ?1
*/
List<Person> findByNameLike(String name);
/**
*通过名字和地址查询,参数为name和address
*相当于JPQL:select p from Person p where p.name = ?1 and p.address = ?2
*/
List<Person> findByNameAndAddress(String name,String address);
}
4.2 使用JPA的NamedQuery查询
支持JPA的NameQuery来定义查询方法,即一个名称映射一个查询语句。
@Entity
@NamedQuery(name="Person.myFindByName",query="select p from Person where p.name=?1")
public class Person{
@Id
@GeneratedValue
private int id;
private String name;
private Integer age;
private String address;
//set get
}
public interface PersonRepository extends JpaRepository<Person,Long>{
//定义数据访问操作的方法
/**
*这时我们使用的是NamedQuery里定义的查询语句
*/
List<Person> myFindByName(String anme);
}
4.3 使用@Query查询
/**
*使用索引
*/
public interface PersonRepository extends JpaRepository<Person,Long>{
//定义数据访问操作的方法
@Query("select p from Person p where p.address=?1")
List<Person> myFindByAddress(String address);
}
/**
*使用命名参数
*/
public interface PersonRepository extends JpaRepository<Person,Long>{
//定义数据访问操作的方法
@Query("select p from Person p where p.address= ::address")
List<Person> myFindByAddress(String address);
}
/**
*更新查询
*/
public interface PersonRepository extends JpaRepository<Person,Long>{
//定义数据访问操作的方法
@Modifying
@Query("update Person p set p.name=?1")
int setName(String name); // 返回的int值表示影响的行数
}
4.4 Specification
数据操作接口实现JpaSpecificationExecutor
public interface PersonRepository extends JpaRepository<Person,Long>,JpaSpecificationEcecutor<Person>{
}
public class CustomerSpecs{
public static Specification<Person> personFormHefei(){
return new Specification<Person>(){
//构造查询条件
@Override
public Predicate toPredicate(Root<Person> root,CriteriaQuery<?> query,CriteriaBuilder cb){
return cb.equal(root.get("address"),"合肥");
}
};
}
}
//静态导入
import static com.shm.springbootdemo.util.CustomerSpecs.*;
//使用
List<Person> person = personRepository.findAll(personFormHefeis);
4.5 分页排序
//定义
public interface PersonRepository extends JpaRepository<Person,Long>{
List<Person> findByName(String name,Sort sort);
Page<Person> findByName(String name,Pageable pageable);
}
//排序使用
List<Person> person = personRepository.findByName("xxx",new Sort(Direction.ASC,"age"));
//分页使用
List<Person> person2 = personRepository.findByName("xxx",new PageRequest(0,10));
三. Spring Data JPA
1. 什么是Spring Data REST
Spring Data REST是基于Spring Data的repository之上,可以把 repository 自动输出为REST资源,目前支持Spring Data JPA、Spring Data MongoDB、Spring Data Neo4j、Spring Data GemFire、Spring Data Cassandra的 repository 自动转换成REST服务。注意是自动。简单点说,Spring Data REST把我们需要编写的大量REST模版接口做了自动化实现.
2. restful api
REST是一种设计风格(与具体的语言无关),它的URL主体是资源,是个名词。而且也仅支持HTTP协议,规定了使用HTTP Method表达本次要做的动作,类型一般也不超过那四五种。这些动作表达了对资源仅有的几种转化方式。
常用的HTTP动词有下面五个(括号里是对应的SQL命令)。
GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
DELETE(DELETE):从服务器删除资源。
HEAD:获取资源的元数据。
OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
3. 实现
Spring Boot 2.0.0.RELEASE
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
配置
# DATA REST (RepositoryRestProperties)
spring.data.rest.base-path= # Base path to be used by Spring Data REST to expose repository resources.
spring.data.rest.default-page-size= # Default size of pages.
spring.data.rest.detection-strategy=default # Strategy to use to determine which repositories get exposed.
spring.data.rest.enable-enum-translation= # Enable enum value translation via the Spring Data REST default resource bundle.
spring.data.rest.limit-param-name= # Name of the URL query string parameter that indicates how many results to return at once.
spring.data.rest.max-page-size= # Maximum size of pages.
spring.data.rest.page-param-name= # Name of the URL query string parameter that indicates what page to return.
spring.data.rest.return-body-on-create= # Return a response body after creating an entity.
spring.data.rest.return-body-on-update= # Return a response body after updating an entity.
spring.data.rest.sort-param-name= # Name of the URL query string parameter that indicates what direction to sort results.
四.声明式事务
1. spring的事务机制
所有的数据访问技术都有事务处理机制,这些结束提供了API用来开启事务,提交事务来完成数据操作,或者在发生错误的时候回滚数据。
而spring的事务机制是统一的机制来处理不同数据访问技术的事务处理。spring的事务机制提供了一个PlatformTranasctionManager接口,不同的数据访问技术的事务使用不同的接口实现。
数据访问技术 | 实现 |
JDBC | DatatSourceTrancactionManager |
JPA | JpaTrancactionManager |
Hibernate | HibernateTrancactionManager |
JDO | JdoTrancactionManager |
分布式事务 | JtaTrancactionManager |
2. 声明式事务
spring支持声明式事务,即是用注解来选择需要使用事务的方法,他使用@Transactional注解在方法上表明该方法需要事务支持。这是一个基于AOP的实现操作。被注解的方法在被调用时,spring开启要给新的事务,方法无异常运行结束后,spirng会提交这个事务。
@Trancactional
public void saveSonmething(){
//操作
}
spring提供一个@EnableTransactionManagement注解在配置类上来开启声名式事务的支持。使用该注解后,spring容器会自动扫描注解@Transcaction的方法和类
@Configuration
@EnableTransactionManagement
public class AppConfig{
}
3. 注解事务行为
数名称 | 功能描述 |
readOnly | 该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true) |
rollbackFor | 该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如: 指定单一异常类:@Transactional(rollbackFor=RuntimeException.class) 指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class}) |
rollbackForClassName | 该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如: 指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException") 指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"}) |
noRollbackFor | 该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如: 指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class) 指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class}) |
noRollbackForClassName | 该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如: 指定单一异常类名称:@Transactional(noRollbackForClassName="RuntimeException") 指定多个异常类名称: @Transactional(noRollbackForClassName={"RuntimeException","Exception"}) |
propagation | 该属性用于设置事务的传播行为,具体取值可参考表6-7。 例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true) |
isolation | 该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置 |
timeout | 该属性用于设置事务的超时秒数,默认值为-1表示永不超时 |
4. 类级别使用@Transactional
@Transactional不仅可以注解在方法上,也可以注解在类上。当注解在类上的时候以为这此类的所有public方法都是开启事务的。如果类和方法同时使用注解,则类级别的注解会重载方法级别的注解。
5. Spring Data JPA的事务支持
Spring Data JPA对所有的默认方法都开启了事务支持,并且插叙类事务默认开启readOnly=true属性。
6.Spring Boot的事务支持
springboot默认自动配置事务管理器,并且自动开启注解事务的支持