- JPA/Hibernate/Spring Data JPA概念
- Spring Data JPA访问数据库
- Spring Data Jdbc Template访问数据库
- Spring Boot集成MyBatis
Java访问数据库经历了几个阶段:
直接通过JDBC访问----ORM框架(如MyBatis、Hibernate)----Spring Data JPA(默认通过Hibernate实现)
- JPA/Hibernate/Spring Data JPA概念
ORM:Object/Relation Mapping,对象/关系型数据库映射,完成面向对象的编程语言到关系型数据库的映射,可以把ORM当成应用程序和数据库的桥梁
最终面向对象数据库会取代关系型数据库,但是关系型数据库系统的某些优势是面向对象语言目前无法比拟的
只要依然采用面向对象程序设计语言,底层依然采用关系型数据库,中间就少不了ORM工具
ORM工具的唯一作用:把持久化对象的保存、修改、删除等操作,转换成对数据库的操作
ORM工具提供了持久化类和数据表之间的映射关系:
数据表-映射-类:持久化类被映射到一个数据表
数据表的行-映射-对象(即实例):每个持久化对象对应数据表的一行记录
数据表的列(字段)-映射-对象的属性
CRUD:
create:增加、retrieve:读取、update:更新、delete:删除
流行的ORM框架:
持久化(Persistence):把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)
持久化的主要应用:将内存中的对象存储在数据库中,或者存储在磁盘文件、XML数据文件中等,JDBC就是一种持久化机制
JPA:Java Persistence API,官方提出的Java持久化规范
JPA的主要实现有:Hibernate、EclipseLink、OpenJPA等,遵循此规范设计
Spring Data:Spring的一个子项目,用于简化数据库访问
Spring Data JPA:Spring Data框架中的一个模块,为了简化JPA的写法
- Spring Data JPA访问数据库
Spring Data:提供了访问操作数据的统一规范,该规范约束了对于关系型和非关系型数据库操作的统一标准,主要包含CRUD(增加、查询、修改、删除)操作、相关参数查询、分页操作、排序操作等
Spring Data通过提供Repository接口来约定数据访问的统一标准,包含如下常用子接口:
CrudRepository、PagingAndSortingRepository、JpaRepository
CrudRepository:提供最基本的对实体类的增删改查操作
1、修改pom.xml文件
//添加MySQL依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
//添加Spring Data JPA依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
spring-boot-starter-data-jpa是Spring Boot项目访问数据库的核心依赖配置
2、在application.properties中配置数据源和JPA相关属性
//数据源信息配置
spring.datasource.url = jdbc:mysql://localhost:3306/springdatajpa
spring.datasource.username = root
spring.datasource.password = ****
spring.datasource.driverClassName = com.mysql.jdbc.Driver
……
//JPA持久化配置
spring.jpa.database = MySQL
#如果数据库中存在持久化类对应的表就不创建,不存在就创建对应的表
spring.jpa.hibernate.ddl-auto = update
……
3、创建持久化类User
新建4个包:bean(放置持久类)、controller(控制器)、repository(定义数据访问接口的包)、service(业务逻辑处理类)
@Entity:用于标记持久化类
@Id:指定主键
@GeneratedValue(strategy=GenerationType.IDENTITY):指定主键的生成策略,MySQL默认为自增长
4、定义数据访问层接口
public interface UserRepository extends CrudRepository<User,Integer>
第一个参数User:持久化对象,第二个参数Integer:指定ID的类型为整型
5、定义业务层
@Service
public class UserService {......}
//注入接口类UserRepository,将接口对应的实现类注入进来
@Resource
private UserRepository userRepository;
使用@Transaction进行事务的绑定:save、update、delete方法需要绑定事务
6、定义控制器类
在controller包下新建一个控制器类:UserController.java
@RestController
@RequestMapping("/user")
//注入UserService
@Resource
private UserService userService;
getAll()返回的是JSON格式的字符串
PagingAndSortingRepository:继承自CrudRepository接口,除了CrudRepository接口的功能之外,还提供了分页与排序功能
1、修改pom.xml文件(与CrudRepository接口访问数据相同)
2、在application.properties中配置数据源和JPA相关属性(与CrudRepository接口访问数据相同)
3、创建持久化类Article
4、定义数据访问层接口
public interface ArticleRepository extends PagingAndSortingRepository<Article,Integer>
5、定义业务层
@Service
public class ArticleService {......}
@Resource
private ArticleRepository articleRepository;
6、定义控制器类
在controller包下新建一个控制器类:ArticleController.java
@RestController
@RequestMapping("/article")
//注入ArticleService
@Resource
private ArticleService articleService;
//根据id进行降序
Sort sort = new Sort(Sort.Direction.DESC,”id”);
//参数1:当前查询的是第几页,默认从0开始,0表示第1页
//参数2:每页展示多少数据
//参数3:封装排序对象
Pageable page = PageRequest.of(pageIndex-1,2,sort);
//分页
Page<Article> articleDatas = articleService.findAll(page);
http://127.0.0.1:8080/article/pager?pageIndex=1
数据以JSON格式返回浏览器
JpaRepository:继承了PagingAndSortingRepository接口,极大地减少了JPA作为数据访问的代码,是实现Spring Data JPA技术访问数据库的关键接口
①简单条件查询 | 查询的方法名称必须以find、get、read开头,条件属性的首字母必须大写 定义数据访问层接口StudentRepository: 因为by是条件关键字,而name是条件属性,条件关键字和条件属性的首字母必须大写,所以上述方法名的定义即findByName 定义业务层StudentService: |
②关联查询和@Query查询 | 对于两个有关联关系的对象的查询,可以通过方法名中的“_”下划线来标识,Spring Data JPA还支持用@Query注解定义在数据访问层接口的方法上实现查询 创建持久化类Student.java和Clazz.java: 定义数据访问层接口ClazzRepository、StudentRepository: List<Student> findByClazz_name(String clazzName):是关联查询的方法,关联的属性可以用下划线“_”连接 @Query注解中可以直接定义JPQL语句进行数据的访问操作 返回多个字段:返回List<Map<String,Object>>对象 @Param注解用于声明参数的名称 Spring Data JPA支持使用@Modifying和@Query注解组合更新查询操作 |
③@NamedQuery查询 | Spring Data JPA支持使用JPA的NameQuery定义查询操作,即一个名称映射一个查询语句 在Student.java中定义NameQuery查询: NameQuery语句应该放到要查询的实体上,并且名称是“实体的类名.方法名称” 定义数据访问层接口StudentRepository: |
④Specification查询 | JPA允许基于Criteria对象进行按条件查询,Specification接口封装了JPA的Criteria查询条件 Specification接口提供了一个toPredicate方法用来构造查询条件,注意:如果自己定义的数据访问层接口希望使用Specification接口的规范,则必须实现JpaSpecificationExecutor接口 JpaSpecificationExecutor接口的源代码:略 定义数据访问层接口ClazzRepository、StudentRepository: 定义业务层类SchoolService.java: root.get(“sex”)表示获取sex这个字段名称,equal表示执行equal查询 封装多个查询条件: 分页查询: 定义分页的页面数据对象PageData.java: |
- Spring Data Jdbc Template访问数据库
Jdbc Template:JDBC模板,为不同类型的JDBC操作提供模板方法,在Maven配置文件中,需要增加spring-boot-starter-jdbc模块
1、在pom.xml文件中增加依赖:
spring-boot-starter-web
spring-boot-starter-thymeleaf
mysql-connector-java
spring-boot-starter-jdbc
2、定义数据访问层接口UserRepository.java:
@Repository //标注这是一个持久化操作对象
public class UserRepository {......}
@Resource
private JdbcTemplate jdbcTemplate; //注入JdbcTemplate模板对象
String sql = “insert into tb_user(login_time,username,password) values (?,?,?),(?,?,?),(?,?,?)”
Object[] args = new Object[]{“swk”,”孙悟空”,”123456”,“zbj”,”猪八戒”,”123456”,“tsz”,”唐三藏”,”123456”}
return jdbcTemplate.update(sql,args); //参数1:插入数据的SQL语句,参数2:对应SQL语句中占位符?的参数
定义一个RowMapper:
RowMapper<User> rowMapper = new BeanPropertyRowMapper<>(User.class);
执行查询方法:
User user = jdbcTemplate.queryForObject(sql,new Object[] {username},rowMapper);
UserRepository类需要通过@Repository注解声明这是一个数据访问层对象,这样在业务层就可以通过注解注入UserRepository对象了
数据库中创建tb_user表:
id INT PRIMARY KEY AUTO_INCREMENT //主键,自增长
- Spring Boot集成MyBatis
MyBatis是一个数据持久层(ORM)框架,在实体类和SQL语句之间建立了映射关系
1、在pom.xml文件中增加依赖:
spring-boot-starter-web
spring-boot-starter-thymeleaf
mysql-connector-java
mybatis-spring-boot-starter
2、定义数据访问层接口UserRepository.java:
public interface UserRepository {......}
@Insert (“insert into tb_user(login_name,username,password) values (#{loginName},#{username},#{password})”)
public int insertUser(User user);
@Select("select * from tb_user where username = #{username}")
@ResultMap("userResult") //引用id="userResult"的@Results
public User selectByUsername(@Param("username") String username);
@Results用于映射对象属性和数据库列,常用于对象属性和数据库列不同名的情况
数据插入成功以后,MyBatis框架会将插入成功的数据主键存入user对象
3、启动类中指定数据访问层接口的包名
@MapperScan("org.fkit.springbootmybatistest.repository") //该注解的参数是一个包名字符串