文章目录
1. SpringBoot整合Spring data jpa
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 添加数据库连接池 druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
@GeneratedValue(strategy=GenerationType.xxx)
指定主键的生成策略IDENTITY
:根据数据库的主键自增长策略GenerationType.TABLE
:使用一个特定的数据库表格来保存主键GenerationType.SEQUENCE
:在某些数据库中,不支持主键自增长,比如Oracle,其提供了一种叫做”序列(sequence)”的机制生成主键。此时,GenerationType.SEQUENCE就可以作为主键生成策略。该策略的不足之处正好与TABLE相反,由于只有部分数据库(Oracle,PostgreSQL,DB2)支持序列对象,所以该策略一般不应用于其他数据库。类似的,该策略一般与另外一个注解一起使用@SequenceGenerator,@SequenceGenerator注解指定了生成主键的序列.然后JPA会根据注解内容创建一个序列(或使用一个现有的序列)。如果不指定序列,则会自动生成一个序列SEQ_GEN_SEQUENCEGenerationType.AUTO
:把主键生成策略交给持久化引擎(persistence engine),持久化引擎会根据数据库在以上三种主键生成策略中选择其中一种。此种主键生成策略比较常用,由于JPA默认的生成策略就是GenerationType.AUTO,所以使用此种策略时.可以显式的指定@GeneratedValue(strategy = GenerationType.AUTO)也可以直接@GeneratedValue@Id
@GeneratedValue(strategy=GenerationType.IDENTITY) //数据库自增
private Integer id;
spring:
datasource: ## 配置数据源
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://118.31.15.108:3306/jpa?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
username: root
password: ****
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 6000
timeBetweenEvictionRunsMillis: 6000
minEvictableIdleTimeMillis: 25200000
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
validationQuery: SELECT 1 FROM DUAL
RemoveAbandanded: true
removeAbandonedTimeout: 1800
logAbandoned: true
jpa:
show-sql: true #控制台打印sql语句
database: MYSQL # 指定数据库的类型,不填会默认检测
generate-ddl: false ## 是否自动生成表,默认是false
# hibernate:
# ddl-auto: update
/**
* 用户的实体类,其中的变量和数据库默认是以驼峰形式对应的,比如industryId,那么在表中的字段一定要是industry_id,否则将会报错
*/
@Table(name="t_user") //指定对应数据库对应的表名
@Entity //标记这是一个实体类
@Data //lombook的自动生成set,get
public class User {
@Id //标记主键
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer age;
private String address;
private Integer industryId; //在数据库中的对应字段一定要是industry_id
}
UserRepository
,相当于Mybatis中的Mapper,如下:import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import cn.tedu.jpa.domain.User;
import java.lang.String;
/**
* JpaRepository的接口,相当于mapper
* 泛型:JpaRepository<User, Integer> :第一个是实体类的类型,第二个是主键的类型
*/
public interface UserRepository extends JpaRepository<User, Integer>{
/**
* 根据指定条件查询 Byxxx(where xxx=xxx),除了根据主键查询,否则返回的都是List
* 其中查询的条件对应的类型必须相同
*/
List<User> findByName(String name);
/**
* 并列条件查询 ,相当于where name=xxx and age=xxx
*/
List<User> findByNameAndAge(String name,Integer age);
/*
* 三个条件的并列查询 where xxx and xxx and xxx
*/
List<User> findByNameAndAgeAndIndustryId(String name,Integer age,Integer industryId);
/*
* Top或者First指定返回结果数量,默认返回第一个,相当于limit 1
*/
User findTopByNameAndAge(String name,Integer age);
/*
* Topn或者Firstn指定返回结果数量,这里的n表示返回的数量,相当于limit n
*/
List<User> findTop2ByNameAndAge(String name,Integer age);
/*
* In 相当于where age in(....) 其中的变量类型可以数组、List、Set只要是Collection即可,泛型必须和查询条件的类型一致
*/
List<User> findByAgeIn(Integer[] ages);
/*
* 统计数据 相当于select count(*) where age=xxx
*/
Long countByAge(Integer age);
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaServerApplicationTests {
@Resource
private UserRepository userRepository;
/**
* 新增数据(单个)
*/
@Test
public void addUser() {
User user=new User();
user.setAge(22);
user.setName("陈加兵");
User user2 = userRepository.save(user); //自增主键的返回
System.out.println(user);
}
/**
* 批量插入
*/
@Test
public void saveAll() {
User user1=new User();
user1.setAge(22);
user1.setName("陈加兵");
User user2=new User();
user2.setAge(22);
user2.setName("陈加兵");
List<User> users=new ArrayList<>();
users.add(user1);
users.add(user2);
List<User> usersResturn=userRepository.saveAll(users); //返回列表,自增主键的返回
for (User user : usersResturn) {
System.out.println(user);
}
}
/**
* 更新数据,使用的仍然是save方法,如果其中包含id,那么就是更新数据,否则就是添加
* 1、如果有数据不更新,那么就出入null即可
*/
@Test
public void update() {
User user1=new User();
user1.setId(1);
user1.setAge(22);
user1.setName("郑元梅");
User user = userRepository.save(user1);
System.out.println(user);
}
/**
* 统计数据
*/
@Test
public void count() {
System.out.println(userRepository.count());
}
/**
* 统计数据
*/
@Test
public void countByAge() {
System.out.println(userRepository.countByAge(23));
}
@Test
public void findByName() {
List<User> users=userRepository.findTop2ByNameAndAge("陈加兵", 22);
for (User user : users) {
System.out.println(user);
}
}
@Test
public void findByAgeIn() {
Integer[] ages= {22,23};
List<User> users=userRepository.findByAgeIn(ages);
for (User user : users) {
System.out.println(user);
}
}
}
}
/**
* 使用hql表达式查询,其中?1表示对应第一个参数,不能直接使用?作为占位符
*/
@Query(value="select u from User u where u.age=?1 and u.name=?2")
List<User> findUserList(Integer age,String name);
nativeQuery=true
/**
* 使用sql语句查询,其中nativeQuery表示使用本地查询,即是sql语句查询
*/
@Query(value="select * from t_user where age=?1 order by industry_id desc",nativeQuery=true)
List<User> findUserListByAge(Integer age);
@Modifying
标注/**
* 删除和修改信息,必须同时使用@Modifying注解标注
*/
@Modifying
@Query(value="delete from t_user where industry_id=?1",nativeQuery=true)
void deleteByIndustryId(Integer industryId);
JpaSpecificationExecutor
,如下:public interface UserRepository extends JpaRepository<User, Integer>,JpaSpecificationExecutor<User>{
/**
* 结果筛选
* @param user 封装了查询的条件
* @return
*/
public List<User> findAll_2(User user) {
List<User> users = userRepository.findAll(new Specification<User>() {
/**
* @param root 根对象,用于封装查询的条件,比如name,jack、age 10等
* @param query 封装查询关键字 比如group by order by
* @param criteriaBuilder 封装对象条件
* @return 返回null表示没有查询条件
*/
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
//new 一个集合,存放所有的查询条件
List<Predicate> predicates=new ArrayList<>();
if (!StringUtils.isEmpty(user.getName())) { //如果name不是null,就填入到筛选条件中
//第一个参数是表达式,第二个参数是值,相当于where name=%name%
Predicate predicate = criteriaBuilder.like(root.get("name").as(String.class),"%"+user.getName()+"%");
predicates.add(predicate); //加入到条件集合中
}
if (!StringUtils.isEmpty(user.getAddress())) { //如果地址不为空,填入筛选条件
//where address=xxx
Predicate predicate = criteriaBuilder.equal(root.get("address").as(String.class), user.getAddress());
predicates.add(predicate);
}
if (user.getAge()!=null) { //如果年龄不为空
//where age<=xxx
Predicate predicate = criteriaBuilder.le(root.get("age").as(Integer.class), user.getAge());
predicates.add(predicate);
}
Predicate[] parray=new Predicate[predicates.size()];
//返回,这里的使用的and条件,将上面所有的条件用and连接
return criteriaBuilder.and(predicates.toArray(parray));
}
});
return users;
}
/**
* 测试
*/
@Test
public void test1() {
User user=new User();
user.setName("a"); //封装name
List<User> users = findAll_2(user);
for (User user2 : users) {
System.out.println(user2);
}
}
public PageRequest(int page, int size)
size
:每页查询的大小page
:从第几页开始,从0开始,0 表示第一页public PageRequest(int page, int size, Direction direction, String... properties)
direction
: 排序的方式,枚举类,其中有ASC,DESCproperties
: 进行排序的字段,可以指定多个int getTotalPages()
:返回共有多少页数long getTotalElements()
:获取总数boolean hasContent();
: 当前分页是否有数据List<T> getContent();
: 返回当前页所有的数据boolean isFirst();
:判断当前的页数是否是第一页boolean isLast();
: 是否是最后页boolean hasNext();
: 是否还有下一页boolean hasPrevious();
: 是否还有前一页Pageable nextPageable();
: 获取下一页Pageable previousPageable();
:获取前一页@Test
public void findAll() {
//构造分页数据,查找第二页,每页2条记录,order by age,industryId desc
Pageable pageable=new PageRequest(1, 2,Direction.DESC,"age","industryId");
Page<User> pages = userRepository.findAll(pageable); //执行分页查询的方法
if (pages.hasContent()) { //如果查询到了内容
List<User> users = pages.getContent(); //获取查询到的结果
long total = pages.getTotalElements(); //获取总数
}
}
@Test
public void findAll() {
Order order1=new Order(Direction.DESC, "age"); //创建排序方式
Order order2=new Order(Direction.ASC, "industryId");
List<Order> orders=new ArrayList<>(); //放入集合
orders.add(order1);
orders.add(order2);
Sort sort=new Sort(orders); //创建Sort
//构造分页数据,查找第二页,每页2条记录,order by age desc,industryId asc
Pageable pageable=new PageRequest(0, 2,sort);
Page<User> pages = userRepository.findAll(pageable); //执行分页查询的方法
if (pages.hasContent()) { //如果查询到了内容
List<User> users = pages.getContent(); //获取查询到的结果
long total = pages.getTotalElements(); //获取总数
for (User user : users) {
System.out.println(user);
}
}
}
/*
* 根据条件查询的结果分页,相当于select * from user where name=xxx limit #,#
*/
List<User> findByName(String name,Pageable pageable);
JpaSpecificationExecutor
,如下:public interface UserRepository extends JpaRepository<User, Integer>,JpaSpecificationExecutor<User>{
/**
* 结果筛选
* @param user 封装了查询的条件
* @return
*/
public List<User> findAll_3(User user,Integer pageNum,Integer pageSize) {
Pageable pageable=new PageRequest(pageNum-1, pageSize); //分页的查询
Page<User> pages = userRepository.findAll(new Specification<User>() {
/**
* @param root 根对象,用于封装查询的条件,比如name,jack、age 10等
* @param query 封装查询关键字 比如group by order by
* @param criteriaBuilder 封装对象条件
* @return 返回null表示没有查询条件
*/
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
//new 一个集合,存放所有的查询条件
List<Predicate> predicates=new ArrayList<>();
if (!StringUtils.isEmpty(user.getName())) { //如果name不是null,就填入到筛选条件中
//第一个参数是表达式,第二个参数是值,相当于where name=%name%
Predicate predicate = criteriaBuilder.like(root.get("name").as(String.class),"%"+user.getName()+"%");
predicates.add(predicate); //加入到条件集合中
}
if (!StringUtils.isEmpty(user.getAddress())) { //如果地址不为空,填入筛选条件
//where address=xxx
Predicate predicate = criteriaBuilder.equal(root.get("address").as(String.class), user.getAddress());
predicates.add(predicate);
}
if (user.getAge()!=null) { //如果年龄不为空
//where age<=xxx
Predicate predicate = criteriaBuilder.le(root.get("age").as(Integer.class), user.getAge());
predicates.add(predicate);
}
Predicate[] parray=new Predicate[predicates.size()];
//返回,这里的使用的and条件,将上面所有的条件用and连接
return criteriaBuilder.and(predicates.toArray(parray));
}
},pageable);
return pages.getContent(); //返回结果
}
/**
* 测试
*/
@Test
public void test2() {
User user=new User();
user.setName("a"); //封装name
List<User> users = findAll_3(user,1,10);
for (User user2 : users) {
System.out.println(user2);
}
}
关键词 | 样品 | JPQL代码段 |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstname,findByFirstnameIs,findByFirstnameEquals | … where x.firstname = ?1 |
Between | findByStartDateBetween | … where x.startDate between ?1 and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
LessThanEqual | findByAgeLessThanEqual | … where x.age <= ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1(附加参数绑定%) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1(与前置绑定的参数%) |
Containing | findByFirstnameContaining | … where x.firstname like ?1(参数绑定包装%) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection<Age> ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection<Age> ages) | … where x.age not in ?1 |
True | findByActiveTrue() | … where x.active = true |
False | findByActiveFalse() | … where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase | … where UPPER(x.firstame) = UPPER(?1) |
Top或者First | findTopByNameAndAge,findFirstByNameAndAge | where … limit 1 |
Topn或者Firstn | findTop2ByNameAndAge,findFirst2ByNameAndAge | where … limit 2 |
Distinct | findDistinctPeopleByLastnameOrFirstname | select distinct …. |
count | countByAge,count | select count(*) |