相关概念
JPA由来
主要的原因是:其一,简化现有Java EE 和 Java SE 应用开发工作,其二,Sun希望整合ORM技术,实现统一的API调用接口。
JPA是什么?
JPA(Java Persistence API)是Sun 官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现有Hibernate、TopLink、JDO等ORM框架各自为营的局面。
注意:JPA是一套规范,不是一套产品,那么像Hibernate、TopLink、JDO它们是一套产品,如果说这些产品实现了这个JPA规范,那么我们就可以称他们为JPA的实现产品,其实就相当于JPA与Habernate这些产品的关系,就类似于类与对象的关系。
Spring Data JPA
Spring Data是Spring的一个子项目,同于简化数据库访问,包括NoSQL非关系型数据库,另外还包括对关系型数据库的访问支持。SpringData使我们可以快速地使用简单地使用普通的数据访问技术及新的数据访问技术,Spring Data会让数据的访问变得更加方便。
Spring Data 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它的实现。
快速上手
1.数据库表
先准备好一个User表
2.创建项目
这篇就不详细讲了,在上一篇博客中可以查看如何详细快速创建Spring Boot项目上篇博客传送门
但是要记得添加相关的依赖(Spring Data JPA , MySQL Driver)
项目pom.xml文件如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3.application.properties添加配置信息
#配置数据源相关信息
#MySQL5.x版本的驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/crm?useUnicode=true&characterEncoding=utf-8
#配置JPA相关信息
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
4.编写实体类:User.java
@Data
@Entity
@Table(name="sys_user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "usr_id")
private Long usrId;
@Column(name="usr_name")
private String usrName;
@Column(name="usr_password")
private String usrPassword;
@Column(name="usr_role_id")
private Long usrRoleId;
@Column(name="usr_flag")
private Integer usrFlag;
}
JPA注解详细说明如下:
- @Entity(name=“EntityName”)必须,用来标注一个数据库表对应的实体,数据库中创建的表明默认和类名一致,其中,name可选,对应数据库中的一个表,使用此注解标记Pojo是一个JPA实体。
- @Table(name="",catalog="",schema="")可选,用来标注一个数据库对应的实体类,数据库中创建的表明默认和类名一致,通常和@Entity配合使用,只能标注在实体的class定义处,表示实体对应的数据库表的信息
- @Id必须,@Id定义了映射到据库表的主键的属性,一个实体只能有一个属性被映射为主键。
4.编写Repository(仓库)
创建UserRository.java
public interface UserRepository extends JpaRepository<User,Long>{
}
5.编写测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Resource
private UserRepository userRepository;
@Test
public void testInsert(){//测试新增
User user=new User();
user.setUsrName("哇哈哈哈哈哈hh");
user.setUsrPassword("123456");
userRepository.save(user);
Assert.assertNotNull(user);
}
@Test
public void testGet(){//测试按主键查询
User user=userRepository.findById(2L).get();
System.out.println("userName:"+user.getUsrName());
}
}
核心功能
基本操作
我们可以将Spring Data JPA基本操作分为两种,一种是Spring Data JPA 默认实现的,另一种是需要根据查询的情况来自行构建。
1.预生成方法
2.自定义查询
Spring Data JPA 还可以根据接口方法来实现数据库操作,主要的语法是findXXBy、queryXXBy、countXXBy、getXXBy后面跟属性名称,利用这个功能仅需要在定义的Repository中添加对应的方法名即可,使用时Spring Boot会自动帮我们实现。
根据用户名查询用户:
public List<User> findByUsrName(String usrName);
基本上SQL体系中的关键字都可以使用,如Like、IgnoreCase、OrderBy:
public List<User> findByUsrNameLike(String usrName);
编写测试方法:
@Test
public void testFindByUerNameLike(){//自定义QL查询
List<User> userList=userRepository.findByUsrNameLike("%哈%");
userList.forEach(u-> System.out.println(u));
}
复杂操作
1.自定义QL查询
在Repository的查询方法上面使用@Query注解,在注解内写HQL来查询内容。
/*@Query("select u from User u where u.usrRoleId=?1")
public List<User> findByRoleId(Long roleId);*/
/*@Query(value="select * from sys_user where usr_role=?1",nativeQuery = true)
public List<User> findByRoleId(Long roleId);*/
@Query("select u from User u where u.usrRoleId=:roleId")
public List<User> findByRoleId(@Param("roleId") Long roleId);
@Transactional(timeout = 10)
@Modifying
@Query("update User u set u.usrName=?1 where u.usrId=?2")
public int modifyNameById(String usrName,Long usrId);
2.分页查询
@Test
public void testFindPageByUsrRoleId(){//简单分页查询
int page=0,size=2;
Sort sort=new Sort(Sort.Direction.DESC,"usrId");
Pageable pageable= PageRequest.of(page,size,sort);
Page<User> userPage=userRepository.findPageBuUsrRoleId(1L,pageable);
userPage.forEach(user -> System.out.println(user));
}
3.复杂查询
定义UserRepository接口及实现类
public interface UserService {
public Page<User> findPageByMap(Map param, Pageable pageable);
}
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserRepository userRepository;
@Override
public Page<User> findPageByMap(Map param, Pageable pageable) {
return userRepository.findAll(new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
if (param.get("usrName") != null) {
predicates.add(criteriaBuilder.like(root.get("usrName"), "%" + param.get("usrName") + "%"));
}
if (param.get("roleId") != null) {
predicates.add(criteriaBuilder.equal(root.get("usrRoleId"), param.get("roleId")));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
}, pageable);
}
}
测试类:
@Test
public void testFindPageByMap(){//复杂分页查询
int page=0,size=2;
Sort sort=new Sort(Sort.Direction.DESC,"usrId");
Pageable pageable= PageRequest.of(page,size,sort);
Map param=new HashMap();
param.put("roleId",1L);
Page<User> userPage=userService.findPageByMap(param,pageable);
userPage.forEach(user -> System.out.println(user));
}