目录
Spring Data JPA简介
JPA(Java Persistence API)是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate、TopLink、JDO 等 ORM 框架各自为营的局面。值得注意的是,JPA 是在充分吸收了现有 Hibernate、TopLink、JDO 等 ORM 框架的基础上发展而来的,具有易于使用、伸缩性强等优点。
注意:JPA 是一套规范,不是一套产品,那么像 Hibernate、TopLink、JDO 它们是一套产品,如果说这些产品实现了这个 JPA 规范,那么就可以叫它们为 JPA 的实现产品。
与mybatis对比
- jpa是对象与对象之间的映射,而mybatis是对象和结果集的映射。
- jpa移植性比较好,不用关心用什么数据库,因为mybatis自由写sql语句,所以当项目移植的时候还需要改sql。
- 修改字段时JPA更简单,mybatis需要修改一堆的xml,mapper等文件很麻烦。
mybatis自定义sql,比较灵活,也可以写复杂的sql,JPA只适合简单的单表sql
总结:mybatis和JPA各有优势,如果sql简单,则jpa使用效率更高,如果sql较复杂,需要自定义,则使用mybatis更加顺手。
入手使用
(一)引入依赖
<dependency>
<groupId>org.Springframework.boot</groupId>
<artifactId>Spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
(二)添加配置文件:
spring:
profiles:
active: dev
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/soil
username: lxtest
password: admin
jpa:
hibernate:
ddl-auto: update
show-sql: true
注意: 我是用的是yml的语法,注意空格的长度,show-sql是在jpa下面的,不是hibernate.show-sql>
重点关注下ddl-auto
这个配置项:
create:每次加载 hibernate 时都会删除上一次的生成的表,然后根据 model 类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop:每次加载 hibernate 时根据 model 类生成表,但是 sessionFactory 一关闭,表就自动删除。
update:最常用的属性,第一次加载 hibernate 时根据 model 类会自动建立起表的结构(前提是先建立好数据库),以后加载 hibernate 时根据 model 类自动更新表结构,即使表结构改变了,但表中的行仍然存在,不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate:每次加载 hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
- show-sql:是否打印出自动生产的 SQL,方便调试的时候查看。
(四)实体类
@Entity
@Data
public class User {
@Id
@GeneratedValue
private Integer id;
private String name;
private String pwd;
private Integer age;
public User(){}
}
(五)Repository:
public interface UserRepository extends JpaRepository<User,Integer>{
}
(六)使用:
@GetMapping(value = "/users", produces = { "application/json;charset=UTF-8" })
public List<User> userList(){
return userRepository.findAll();
}
自定义简单查询
Spring Data Jpa有个很赞的功能就是可以自动根据方法名去生成相应的简单sql,具体的方法名和sql如下:
例如:
User findByUserNameOrEmail(String username, String email);
Long countByUserName(String userName);
Long deleteById(Long id);
//获得符合查询条件的前10条数据
List<Person> findFirst10ByName(String name);
//获取符合查询条件的前30条数据
List<Person> findTop30ByName(String name);
具体的方法名和语句如下:
关键字 | 方法命名 | sql where字句 |
---|---|---|
And | findByNameAndPwd | where name= ? and pwd =? |
Or | findByNameOrSex | where name= ? or sex=? |
Is,Equals | findById,findByIdEquals | where id= ? |
Between | findByIdBetween | where id between ? and ? |
LessThan | findByIdLessThan | where id < ? |
LessThanEquals | findByIdLessThanEquals | where id <= ? |
GreaterThan | findByIdGreaterThan | where id > ? |
GreaterThanEquals | findByIdGreaterThanEquals | where id > = ? |
After | findByIdAfter | where id > ? |
Before | findByIdBefore | where id < ? |
IsNull | findByNameIsNull | where name is null |
isNotNull,NotNull | findByNameNotNull | where id= ? |
Like | findByNameLike | where name like ? |
NotLike | findByNameNotLike | where name not like ? |
StartingWith | findByNameStartingWith | where name like ‘?%’ |
EndingWith | findByNameEndingWith | where name like ‘%?’ |
Containing | findByNameContaining | where name like ‘%?%’ |
OrderBy | findByIdOrderByXDesc | where id=? order by x desc |
Not | findByNameNot | where name <> ? |
In | findByIdIn(Collection c) | where id in (?) |
NotIn | findByIdNotIn(Collection c) | where id not in (?) |
True | findByAaaTue | where aaa = true |
False | findByAaaFalse | where aaa = false |
IgnoreCase | findByNameIgnoreCase | where id= ? |
复杂查询
(一)分页
@Query("select u from User u")
Page<User> findALL(Pageable pageable);
Page<User> findByNickName(String nickName, Pageable pageable);
Pageable 是 Spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。
@Test
public void testPageQuery(){
int page=1,size=10;
Sort sort = new Sort(Direction.DESC, "id");
Pageable pageable = new PageRequest(page, size, sort);
userRepository.findALL(pageable);
userRepository.findByNickName("testName", pageable);
}
(二)限制查询
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> findTop10ByLastname(String lastname, Pageable pageable);
(三)自定义SQL
在 SQL 的查询方法上面使用 @Query 注解,如涉及到删除和修改需要加上 @Modifying,也可以根据需要添加 @Transactional 对事物的支持,查询超时的设置等。
@Transactional(timeout = 15)
@Modifying
@Query("update User set name= ?1 where id = ?2")
int modifyById(String name, Long id);
@Transactional
@Modifying
@Query("delete from User where id = ?1")
void deleteById(Long id);
@Query("select u from User u where u.pwd= ?1")
User findByPwd(String pwd);
(四)多表查询
再新建一个用户详情的实体类:
@Data
@Entity
public class UserInfo {
@Id
@GeneratedValue
private Integer id;
private Integer userId;
private String address;
private String tel;
}
再新建一个接口,用于接受连表查询结果。
/**
* @author : Aslan
* @version : v1.0
* @time : 2018-06-26 14:11
* @desc : 定义一个结果集的接口类,接口类的内容来自于用户表和用户详情表,用于接收连表查询后的结果
*/
public interface UserDetail {
String getTel();
String getAddress();
String getName();
}
新建一个Repository,也就是类似于DAO。
public interface UserInfoRepository extends JpaRepository<UserInfo,Integer> {
/**
* 特别注意这里的 SQL 是 HQL,需要写类的名和属性,不是数据库里面的字段名,若写错则会报错:
*
* 传入电话,查找用户信息
* @param tel
* @return
*/
@Query("select u.name,d.address,d.tel from User u , UserInfo d " +
"where u.id = d.userId and d.tel = ?1 ")
List<UserDetail> findUserInfo(String tel);
}
使用:
@GetMapping(value = "/testUserInfo")
public void testUserInfo(){
List<UserDetail> userDetails = userInfoRepository.findUserInfo("111");
for(UserDetail detail: userDetails){
System.out.println("name = "+detail.getName());
}
}