JPA(Java Persistence API)
意即Java持久化API,是Sun官方在JDK5.0后提出的Java持久化规范,JPA的出现主要是为了简化持久层开发以及整合ORM技术,结束Hibernate、TopLink、JDO等ORM框架各自为营的局面。JPA是在吸收现有ORM框架的基础上发展而来,易于使用,伸缩性强。
总的来说,JPA包括以下3方面的技术:
ORM映射:支持XML和注解描述对象和表之间的映射关系
API:操作实体对象来执行CRUD(create read update delete)(增删改查)操作
查询语言:通过面向对象而非面向数据库的查询语言(JPQL)查询数据
Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。Spring Data JPA不需要过多的关心Dao层的实现,只需关注我们继承的接口,按照一定的规则去编写我们的接口即可,spring会按照规范动态生成我们接口的实现类进行注入,并且实现类里包含了一些常规操作的方法实现。如果使用JPA提供的接口来操作ORM框架,可以不写任何实现就能对数据库进行CRUD操作,还可以进行简单的分页,排序操作。
Repository:
所有接口的父接口,而且是一个空接口,目的是为了统一所有Repository的类型,让组件扫描的时候能进行识别。
CrudRepository:
是Repository的子接口,提供CRUD(增删改查)的功能。
PagingAndSortingRepository:
是CrudRepository的子接口,添加分页和排序的功能。
JpaRepository:
是PagingAndSortingRepository的子接口,增加了一些实用的功能,例如批量操作。
JpaSpecificationExecutor:用来做负责动态条件查询的接口。
Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可。
**1.在项目的pom.xml中添加spring-data-jpa的依赖配置
c3p0
c3p0
${c3p0.version}
org.springframework.data
spring-data-jpa
1.9.0.RELEASE
2.在spring核心配置文件中配置spring-data-jpa相关项
applicationContext.xml
与hibernate Mybatis配置一样
3.编写实体类并使用JPA注解配置实体类和数据库表的映射关系
JPA不需要自己创建数据库,只需要在实体类中通过注解配置好,就会自动创建出所需要的数据
注意:日期这块要特别注意
User.class
//name="t_user" 数据库的表名
@Table(name="t_user")
//@Entity表明是一个实体类
@Entity
public class User {
@Id
//指名这是一个主键,auto会自动根据方言来生成主键,IDENTITY mysql的主键生成
@GeneratedValue(strategy = GenerationType.AUTO)
//@Column 字段名,类型会自动根据属性类型匹配,如果不写,默认就是属性名
@Column(name="user_id")
private Integer userId;
//定义字段名
@Column(name="user_name")
private String userName;
@Column(name="real_name")
private String realName;//真实姓名
@Column(name="user_sex")
private Integer userSex;//性别
//@DateTimeFormat是日期的展示格式
//加上后,格式为:2020-01-01
//不加: 默认格式为:2020-01-01 12:03:22
@DateTimeFormat(pattern = "yyyy-MM-dd")
//@Temporal设置数据库的字段类型 ,
///加上为:date类型(2020-01-01)
//不加默认:datetime(2020-01-01 12:03:22)
//与@DateTimeFormat一定要对应好
@Temporal(TemporalType.DATE)
@Column(name="user_birthday")
//json数据的展示
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private Date userBirthday;//生日
//创建日期有时分秒
//不能省略
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name="create_date")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date createDate;//创建时间
//不能省略
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name="update_Date")
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private Date updateDate;//修改时间
//生成getter setter方法
}
service serviceImpl
Repository 替代了dao层
这里通过junit进行测试,所以需要导入相关的jar包
junit
junit
4.12
Repository.java
/**
* Repository替代了dao类
* 需要继承extends JpaRepository Integer 是id的类型
* 只要继承该类,就会自动有增删改查 的方法,直接可以调用
* @author srj
*
*继承JpaRepository(增删改查),
*第一个泛型:我们要操作的实体类,
*第二个泛型:主键属性的数据类型
*/
public interface UserRepository extends JpaRepository{
//只要继承JpaRepository,默认会有增删改查的方法,直接调用就可以
}
测试类
UserRepositoryTest.java
//用于指定junit运行环境,是junit提供给其他框架测试环境接口扩展,为了便于使用spring的依赖注入
//spring提供了org.springframework.test.context.junit4.SpringJUnit4ClassRunner作为Junit测试环境
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
}
准备完成:
UserRepositoryTest.java
/**
* 新增
*/
@Test
public void addUser() {
User user = new User();
user.setUserName("李四111");
user.setUserSex(2);
user.setUserBirthday(new Date());
//直接调用新增方法即可
userRepository.saveAndFlush(user);
}
/**
* 删除
*/
@Test
public void deleteUser() {
//直接调用即可
userRepository.delete(2);
}
/**
* 修改
*/
@Test
public void updateUser() {
User user = userRepository.findOne(1);
user.setUserName("小红");
user.setUserEmail("[email protected]");
user.setCreateDate(new Date());
userRepository.saveAndFlush(user);
}
/**
* 查询
*/
@Test
public void queryUser() {
List userList = userRepository.findAll();
//循环输出所有值
for (Iterator iterator = userList.iterator(); iterator.hasNext();) {
User user = (User) iterator.next();
System.out.println(user.getUserName());
}
}
如果要进行特殊查询等,需要继承接口JpaSpecificationExecutor,根据规则自定方法
//继承JpaSpecificationExecutor(复杂查询,动态查询),泛型: 就是我们操作的实体类
Spring Data JPA为自定义查询提供了一些表达条件查询的关键字,大致如下:
And:等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
Or :等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
Between :等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
LessThan:等价于 SQL 中的 “<”,比如 findBySalaryLessThan(int max);
GreaterThan:等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
IsNull :等价于 SQL 中的 “is null”,比如 findByUsernameIsNull();
IsNotNull:等价于 SQL 中的 “is not null”,比如 findByUsernameIsNotNull();
NotNull:与 IsNotNull 等价;
Like :等价于 SQL 中的 “like”,比如 findByUsernameLike(String user);
NotLike :等价于 SQL 中的 “not like”,比如 findByUsernameNotLike(String user);
OrderBy:等价于 SQL 中的 “order by”,比如 findByUsernameOrderBySalaryAsc(String user);
Not:等价于 SQL 中的 “!=”,比如 findByUsernameNot(String user);
In :等价于 SQL 中的 “in”,比如 findByUsernameIn(Collection userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
NotIn:等价于 SQL 中的 “not in”,比如 findByUsernameNotIn(Collection userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
public interface UserDao extends JpaRepository,JpaSpecificationExecutor{
}
And使用
//and
User findByUserNameAndUserSex(String userName,Integer userSex);
/**
* 通过userName和userSex查询
*/
@Test
public void findByUsernameAndUserSexTest() {
User user = userRepository.findByUserNameAndUserSex("李四", 10);
System.out.println(user);
}
between使用
//between
List findByUserSexBetween(int maxSex, int minSex);
/**
* between
*/
@Test
public void findByUserSexBetweenTest() {
List userlist = userRepository.findByUserSexBetween(0, 4);
//循环输出所有值
for (Iterator iterator = userlist.iterator(); iterator.hasNext();) {
User user = (User) iterator.next();
System.out.println(user.getUserName());
}
}
like使用
//like
List findByUserNameLike(String user);
/**
* like
*/
@Test
public void findByUserNameLikeTest() {
//查询姓李的人
List userlist = userRepository.findByUserNameLike("李%");
//循环输出所有值
for (Iterator iterator = userlist.iterator(); iterator.hasNext();) {
User user = (User) iterator.next();
System.out.println(user.getUserName());
}
}
OrderBy使用
//OrderBy:等价于 SQL 中的 "order by",比如
List findByUserNameLikeOrderByUserIdAsc(String user);
/**
* 条件查询+排序
*/
@Test
public void findByUserNameOrderByUserSexAscTest() {
//查询姓李的人
//List userlist = userRepository.findByUserNameOrderByUserIdAsc("");
List userlist = userRepository.findByUserNameLikeOrderByUserIdAsc("李%");
//循环输出所有值
for (Iterator iterator = userlist.iterator(); iterator.hasNext();) {
User user = (User) iterator.next();
System.out.println("name======"+user.getUserName()+"======sex=====");
}
}
一.分页
UserService .java
public interface UserService {
//分页
public List queryPage(Integer pageIndex,Integer pagesize);
}
UserServiceImpl .java
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserRepository userRepository;
/**
* 分页
*/
public List queryPage(Integer pageIndex,Integer pagesize){
//构造分页对象
PageRequest pageRequest = new PageRequest(pageIndex, pagesize);
//开始分页查询获取page对象
Page page = userRepository.findAll(pageRequest);
//查询
List userList = page.getContent();
return userList;
}
}
UserServiceImplTest.java
//用于指定junit运行环境,是junit提供给其他框架测试环境接口扩展,为了便于使用spring的依赖注入
//spring提供了org.springframework.test.context.junit4.SpringJUnit4ClassRunner作为Junit测试环境
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class UserServiceImplTest {
@Autowired
private UserService userService;
/**
* 测试分页
*/
@Test
public void queryPageTest() {
List userList = userService.queryPage(0,2);
for (User user : userList) {
System.out.println(user);
System.out.println(user.getUserName());
}
}
}
二.分页+排序 先排序再分页
UserService .java
//分页+排序
public List queryPageAndSorting(Integer pageIndex,Integer pagesize,String name,Direction orderBy);
UserServiceImpl .java
/**
* 先排序再分页
* 分页+排序
* @param pageIndex 当前第几页 从0开始
* @param pagesize 每页条数
* @param name 按照什么属性【字段名】分页
* @param orderBy 排序规则:asc desc
* @return
*/
public List queryPageAndSorting(Integer pageIndex,Integer pagesize,String name,Direction orderBy){
//排序
Sort sort = new Sort(orderBy,name);
//构建分页对象
PageRequest pageRequest = new PageRequest(pageIndex, pagesize,sort);
//开始分页查询,获取page对象
Page page = userRepository.findAll(pageRequest);
//获取分页的list集合
List userList = page.getContent();
return userList;
}
UserServiceImplTest.java
/**
* 测试分页+排序
*/
@Test
public void queryPageAndSortingTest() {
List userList = userService.queryPageAndSorting(0,2,"userId",Direction.DESC);
for (User user : userList) {
System.out.println(user);
}
}
三.先分页再排序
UserService .java
//分页+排序
public List querySortingAndPage(Integer pageIndex,Integer pagesize,String name,Direction orderBy);
UserServiceImpl .java
/**
* 先分页再排序
* @param pageIndex
* @param pagesize
* @param name
* @param orderBy
* @return
*/
public List querySortingAndPage(Integer pageIndex,Integer pagesize,String name,Direction orderBy){
PageRequest pageRequest = new PageRequest(pageIndex, pagesize);
//开始分页查询,获取page对象
Page page = userRepository.findAll(pageRequest);
Sort sort = new Sort(orderBy,name);
//Sort sort2 = page.getSort();
//获取分页的list集合
List userList = page.getContent();
//排序
PageRequest pageRequest1 = new PageRequest(pageIndex, pagesize,sort);
//开始分页查询,获取page对象
Page page1 = userRepository.findAll(pageRequest);
//获取分页的list集合
List userList1 = page.getContent();
return userList1;
}
UserServiceImplTest.java
@Test
public void querySortingAndPage() {
List userList = userService.querySortingAndPage(0,2,"userId",Direction.DESC);
for (User user : userList) {
System.out.println(user);
}
}