一起来学SpringBoot|一起来学SpringBoot | 第五篇(整合SpringDataJpa)
上一篇介绍了SpringBoot
是为了简化Spring
应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程
Spring JdbcTemplate
的使用,对比原始的JDBC
而言,它更加的简洁。但随着表的增加,重复的CRUD工作让我们苦不堪言,这时候Spring Data Jpa
的作用就体现出来了…..JPA JPA是
Java Persistence API
的简称,中文名Java持久层API,是官方(Sun)在JDK5.0后提出的Java持久化规范。其目的是为了简化现有JAVA EE
和JAVA SE
应用开发工作,以及整合现有的ORM技术实现规范统一JPA的总体思想和现有Hibernate
、TopLink
、JDO
等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
- ORM映射元数据: 支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
- API: 操作实体对象来执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
- 查询语言: 通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
Hibernate
是最为强大的一个。从功能上来说,JPA就是Hibernate功能的一个子集。Hibernate 从3.2开始,就开始兼容JPA。同时Hibernate3.2获得了Sun TCK的JPA(Java Persistence API) 兼容认证。Spring Data JPA 【一起来学SpringBoot|一起来学SpringBoot | 第五篇(整合SpringDataJpa)】常见的ORM框架中
Hibernate
的JPA最为完整,因此Spring Data JPA
是采用基于JPA规范的Hibernate
框架基础下提供了Repository
层的实现。Spring Data Repository
极大地简化了实现各种持久层的数据库访问而写的样板代码量,同时CrudRepository
提供了丰富的CRUD功能去管理实体类。优点
- 丰富的API,简单操作无需编写额外的代码
- 丰富的SQL日志输出
缺点
- 学习成本较大,需要学习HQL
- 配置复杂,虽然
SpringBoot
简化的大量的配置,关系映射多表查询配置依旧不容易 - 性能较差,对比
JdbcTemplate
、Mybatis
等ORM框架,它的性能无异于是最差的
pom.xml
中添加 spring-boot-starter-data-jpa
的依赖
org.springframework.boot
spring-boot-starter-data-jpa
mysql
mysql-connector-java
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
连接数据库
在application.properties中添加如下配置。值得注意的是,SpringBoot默认会自动配置DataSource,它将优先采用HikariCP连接池,如果没有该依赖的情况则选取tomcat-jdbc,如果前两者都不可用最后选取Commons DBCP2。通过spring.datasource.type属性可以指定其它种类的连接池
spring.datasource.url=jdbc:mysql://localhost:3306/chapter5?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
spring.datasource.password=root
spring.datasource.username=root
#spring.datasource.type
# JPA配置
spring.jpa.hibernate.ddl-auto=update
# 输出日志
spring.jpa.show-sql=true
# 数据库类型
spring.jpa.database=mysql
ddl-auto 几种属性
- create: 每次运行程序时,都会重新创建表,故而数据会丢失
- create-drop: 每次运行程序时会先创建表结构,然后待程序结束时清空表
- upadte: 每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用)
- validate: 运行程序会校验数据与数据库的字段类型是否相同,字段不同会报错
spring.jpa.hibernate.ddl-auto=update
方式,因此这里可以跳过手动建表的操作实体类
JPA规范注解坐落在
javax.persistence
包下,@Id
注解一定不要引用错了,否则会报错。@GeneratedValue(strategy = GenerationType.IDENTITY)
自增策略,不需要映射的字段可以通过@Transient
注解排除掉常见的几种自增策略
TABLE: 使用一个特定的数据库表格来保存主键
SEQUENCE: 根据底层数据库的序列来生成主键,条件是数据库支持序列。这个值要与generator一起使用,generator 指定生成主键使用的生成器(可能是orcale中自己编写的序列)。
IDENTITY: 主键由数据库自动生成(主要是支持自动增长的数据库,如mysql)
AUTO: 主键由程序控制,也是GenerationType的默认值。
package com.battcn.entity;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import java.io.Serializable;
/**
* @author
*/
@Entity(name = "t_user")
public class User implements Serializable {private static final long serialVersionUID = 8655851615465363473L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
/**
* TODO 忽略该字段的映射
*/
@Transient
private Stringemail;
// TODO省略get set
}
Repository
创建UserRepository数据访问层接口,需要继承JpaRepository
package com.battcn.repository;
import com.battcn.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* t_user 操作
*
* @author
*/
@Repository
public interface UserRepository extends JpaRepository {/**
* 根据用户名查询用户信息
*
* @param username 用户名
* @return 查询结果
*/
List findAllByUsername(String username);
}
测试
完成数据访问层接口后,最后编写一个junit测试类来检验代码的正确性。
下面的几个操作中,只有findAllByUsername是我们自己编写的代码,其它的都是继承自JpaRepository接口中的方法,更关键的是分页及排序是如此的简单实例化一个Pageable即可…
package com.battcn;
import com.battcn.entity.User;
import com.battcn.repository.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
/**
* @author Levin
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter5ApplicationTests {private static final Logger log = LoggerFactory.getLogger(Chapter5ApplicationTests.class);
@Autowired
private UserRepository userRepository;
@Test
public void test1() throws Exception {
final User user = userRepository.save(new User("u1", "p1"));
log.info("[添加成功] - [{}]", user);
final List u1 = userRepository.findAllByUsername("u1");
log.info("[条件查询] - [{}]", u1);
Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Order.desc("username")));
final Page users = userRepository.findAll(pageable);
log.info("[分页+排序+查询所有] - [{}]", users.getContent());
userRepository.findById(users.getContent().get(0).getId()).ifPresent(user1 -> log.info("[主键查询] - [{}]", user1));
final User edit = userRepository.save(new User(user.getId(), "修改后的ui", "修改后的p1"));
log.info("[修改成功] - [{}]", edit);
userRepository.deleteById(user.getId());
log.info("[删除主键为 {} 成功] - [{}]", user.getId());
}
}
总结 更多内容请参考官方文档
目前很多大佬都写过关于
SpringBoot
的教程了,如有雷同,请多多包涵,本教程基于最新的 spring-boot-starter-parent:2.0.1.RELEASE
编写,包括新版本的特性都会一起介绍…推荐阅读
- 一个人的旅行,三亚
- 慢慢的美丽
- 一个小故事,我的思考。
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量
- 开学第一天(下)
- 一个人的碎碎念
- 2018年11月19日|2018年11月19日 星期一 亲子日记第144篇
- 遇到一哭二闹三打滚的孩子,怎么办┃山伯教育
- 第326天
- Y房东的后半生14