一、SpringDataJpa
Spring Data JPA是Spring Data的子模块。使用Spring Data,使得基于“repositories”概念的JPA实现更简单和容易。Spring Data JPA的目标是大大简化数据访问层代码的编码。使用者只需要编写自己的repository接口,接口中包含一些个性化的查询方法,Spring Data JPA将自动实现查询方法。
Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询,在实现动态查询时我们需要用到Criteria API,主要是以下三个:
- Criteria 查询是以元模型的概念为基础的,元模型是为具体持久化单元的受管实体定义的,这些实体可以是实体类,嵌入类或者映射的父类。
- CriteriaQuery接口:代表一个specific的顶层查询对象,它包含着查询的各个部分,比如:select 、from、where、group by、order by等注意:CriteriaQuery对象只对实体类型或嵌入式类型的Criteria查询起作用
- Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似
二、SpringBoot整合
1、添加相关依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
2、配置文件:
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
username: root
password: admin
driverClassName: com.mysql.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
database-platform: org.hibernate.dialect.MySQL57Dialect
show-sql: true
3、创建映射实体类:
package com.example.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* 路径:com.example.demo.entity
* 类名:
* 功能:《用一句描述一下》
* 备注:
* @Entity 表示该类是一个数据库表映射实体
* @NoArgsConstructor: 自动生成无参数构造函数。
* @AllArgsConstructor: 自动生成全参数构造函数。
* 创建人:typ
* 创建时间:2019/1/21 12:06
* 修改人:
* 修改备注:
* 修改时间:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "user")
public class User {
@Id
private Integer id;
private String username;
private String password;
}
注意:导包不要导错了,都是javax.persistence.*下的包。
相关注解解释:
- @Entity :表示该类是一个数据库表映射实体
- @NoArgsConstructor: 自动生成无参数构造函数。
- @AllArgsConstructor: 自动生成全参数构造函数。
- @Table(name = "user"):与数据库表的映射
4、创建查询接口(UserRepository)继承自CrudRepository,CrudRepository 默认定义了部分增删改查方法:
package com.example.demo.dao;
import com.example.demo.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import java.util.List;
/**
* 路径:com.example.demo.dao
* 类名:
* 功能:查询接口继承自CrudRepository,CrudRepository 默认定义了部分增删改查方法
* 备注:
* 创建人:typ
* 创建时间:2019/1/21 12:06
* 修改人:
* 修改备注:
* 修改时间:
*/
public interface UserRepository extends CrudRepository<User, Integer> {
/**
* 方法名:
* 功能:方法名遵循命名规范的查询
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 14:13
* 修改人:
* 修改描述:
* 修改时间:
*/
List<User> findAllByusername(String username);
/**
* 方法名:
* 功能:分页排序查询
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 14:13
* 修改人:
* 修改描述:
* 修改时间:
*/
Page<User> findAll(Pageable pageable);
/**
* 方法名:
* 功能:传入参数名称
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 15:12
* 修改人:
* 修改描述:
* 修改时间:
*/
@Query("select u from User u where u.username = :username and u.password = :password")
User findByParam(@Param("username") String username, @Param("password") String password);
/**
* 方法名:
* 功能:占位符查询
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 15:17
* 修改人:
* 修改描述:
* 修改时间:
*/
@Query(value = "select u from User u where u.username = ?1 or u.password = ?2")
List<User> findByConditionAndOrder(String username, String password);
}
- 方法名遵循命名规范的查询:此方法的名称必须与实体的name名称对应,我这里是username所以方法名为findAllByusername();
- 使用@Query注解需要注意这里的SQL表名称是实体类的名称,而不是数据库表的名称;
- 占位符查询:不能写成这样 @Query(value = "select u from User u where u.username = ? or u.password = ?"),必须是这样的 @Query(value = "select u from User u where u.username = ?1 or u.password = ?2"),否则会报错的。
5、测试
package com.example.demo;
import com.example.demo.dao.UserRepository;
import com.example.demo.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootDateJpaApplicationTests {
@Autowired
private UserRepository repository;
/**
* 方法名:
* 功能:保存单条数据
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 14:57
* 修改人:
* 修改描述:
* 修改时间:
*/
@Test
public void save() {
repository.save(new User(13, "hello", "hello"));
}
/**
* 方法名:
* 功能:保存多条数据
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 14:56
* 修改人:
* 修改描述:
* 修改时间:
*/
@Test
public void saves() {
List<User> user = new ArrayList<>();
user.add(new User(1, "hello1", "hello"));
user.add(new User(1, "hello2", "hello"));
user.add(new User(1, "hello3", "hello"));
user.add(new User(1, "hello4", "hello"));
repository.saveAll(user);
}
/**
* 方法名:
* 功能:遵循命名规范的查询
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 14:56
* 修改人:
* 修改描述:
* 修改时间:
*/
@Test
public void findByName() {
List<User> users = repository.findAllByusername("hello");
users.forEach(System.out::println);
}
/**
* 方法名:
* 功能:传入参数名称
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 15:13
* 修改人:
* 修改描述:
* 修改时间:
*/
@Test
public void findByParam(){
User user = repository.findByParam("hello","hello");
System.out.println(user);
}
/**
* 方法名:
* 功能:占位符查询
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 15:17
* 修改人:
* 修改描述:
* 修改时间:
*/
@Test
public void findByConditionAndOrder(){
List<User> users = repository.findByConditionAndOrder("hello","hello");
users.forEach(System.out::println);
}
/**
* 方法名:
* 功能:分页查询
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 14:58
* 修改人:
* 修改描述:
* 修改时间:
*/
@Test
public void page() {
Page<User> page = repository.findAll(PageRequest.of(0, 10));
page.forEach(System.out::println);
}
/**
* 方法名:
* 功能:更新数据
* 描述:保存主键相同的数据就认为是更新操作
* 创建人:typ
* 创建时间:2019/1/21 14:58
* 修改人:
* 修改描述:
* 修改时间:
*/
@Test
public void update() {
repository.save(new User(12, "hello1", "0123456"));
}
/**
* 方法名:
* 功能:删除数据
* 描述:
* 创建人:typ
* 创建时间:2019/1/21 15:04
* 修改人:
* 修改描述:
* 修改时间:
*/
@Test
public void delete() {
repository.deleteById(12);
}
}
service层和controller层就不在这里赘述了,和基础的SpringBoot工程是一样的,这里只是实现简单的整合测试功能。