持久层技术,简单来说,就是通过操纵对象来操作数据库。(具体见前言部分)

本期博客继续深入Spring Boot技术,值得一提的是,尽管Spring Boot操作起来还是不错的,看都看明白,但还是强烈建议大家自己动手操作,里面的坑还是很多的,只有经历了自己才知道。一般来说,像Web项目不会精确定位是哪一段代码有什么问题,只会告诉你有一些逻辑问题,大多我在Java里面遇到的就是NULL空指针类型的,寻找错误起来异常麻烦,很多时候都是一个细节需要找很久。(所以真的,Code必须要仔细啊)

本期的数据库操作主要围绕着JdbcTemplate ,MyBatis,Spring Data JPA,不讲JDBC了(第一个也都是使用数据连接池来操作的)

后期的博客主要是整合NoSQL,构建RESTful服务,单元测试,安全管理等,持续更新!(不过我主要还是以后端为主,前端能力依旧差很多,需要在短期补足一下)

目录

  • 前言
  • 整合JdbcTemplate
  • 整合MyBatis
  • 整合Spring Data JPA
  • 多数据源

前言

持久层,可以理解成数据 保存在 数据库或者 硬盘一类可以保存很长时间的设备里面,不像放在内存中那样断电就消失了,也就是把数据存在持久化设备上。
持久化可以通过很多方式,写文件和数据库都可以。只是现在企业一般都会选择把数据持久化到数据库中,因为可以很方便的查询统计分析,但数据库的数据最终还是会写到磁盘上的。Java 程序员为了操作数据库, 最开始是使用JDBC* 来进行的,但是这种方式* 开发效率低 ,要写一堆重复代码,加上关系数据库和对象本身存在所谓的阻抗不匹配情况,所以 为了提高开发效率,有人发明了 ORM 即 对象关系映射框架* (Hibernate是其中的佼佼者),对于 Java 程序员来说,就可以通过操纵对象来操纵数据库了。
持久层是Java EE中访问数据库的核心操作,Spring Boot对常见的持久层框架提供了自动化配置,例如JdbcTemplate,JPA等,MyBatis的自动化配置是MyBatis官方提供的。
其中,JdbcTemplate使用得不是很广泛,MyBatis灵活性较好,方便开发者进行SQL优化。Spring Data JPA使用方便,能快速实现一共RESTful风格的应用。
一般构建目录如下:分为Controller,dao,model,service层相互应用。

整合JdbcTemplate

JdbcTemplate是Spring提供的JDBC模板框架,利用AOP技术来解决使用JDBC时大量重复代码问题。虽没有MyBatis那么灵活但是方便很多。
这里都是以数据连接池为例。

下面以一个实例为例:
建表命令:

create database  chapter05 default character set utf8;
use chapter05;
create table book(**id int(11) not null  auto_increment,**name varchar(128) default null,author varchar(64) default null,primary key (id)
);
insert into book (id, name, author) value (1,'ABC','ACD');

添加依赖:
spring-boot-jdbc提供了spring-jdbc ,例外加入了数据库驱动依赖和数据库连接池依赖。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.2</version></dependency>

数据库配置:
在application.properties配置数据库连接信息:记得配置完依赖需要刷新依赖。

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql:///chapter05
spring.datasource.username = root
spring.datasource.password = qazwsx123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver // 下面版本号为8.0.30

创建book的实体:

public class Book {private   Integer id;private   String name;private  String author;@JsonFormat(pattern = "yyyy-MM-dd")public  Integer getId() {return id;}public  String getName() {return name;}public String getAuthor() {return author;}public void setId(Integer id) {this.id = id;}public void setName(String name) {this.name = name;}public  void setAuthor(String author) {this.author = author;}
}

创建BookDao,创建数据库访问层:

@Repository
public class BookDao {@Autowired(required = false)JdbcTemplate jdbcTemplate;public int addBook(Book book) {return jdbcTemplate.update("insert into book(name ,author) values (?,?)",book.getName(),book.getAuthor());}public int updateBook(Book book) {return jdbcTemplate.update("update book set name=?,author=? where id=?",book.getName(),book.getAuthor(),book.getId());}public int deleteBookById(Integer id) {return jdbcTemplate.update("delete from  book where id =? ",id);}public Book getBookById(Integer id) {return jdbcTemplate.queryForObject("select * from book where id = ?",new BeanPropertyRowMapper<>(Book.class),id);}public List<Book> getAllBooks() {return jdbcTemplate.query("select * from book",new BeanPropertyRowMapper<>(Book.class));}
}

在我没有对AUTOWIRED进行配置的时候,出现了这个错误:Could not autowire. No beans of ‘JdbcTemplate’ type found.
所以需要加上false语句来降低安全性
解释:
注入JdbcTemplate,由于添加了spring-jdbc相关依赖,所以会自动注册到Spring容器,因此可以直接注入JdbcTemplate使用。
增删改三种类型操作主要使用update,batchUpdate来完成。query和queryForObject主要完成查询功能。还有execute来执行任意的SQL,call方法。
在执行查询操作,需要一个RowMapper将查询的列和实体相对应。如果列名和属性名相同,那么可以直接使用BeanPropertyRowMapper,如果列名和属性不同,就需要开发者自己实现RowMapper接口。

创建Service

@Service
public class BookService {@Autowired(required = false)BookDao bookDao;public int addBook(Book book) {System.out.println(book.getId());System.out.println(book.getAuthor());System.out.println(book.getName()+"1233");return bookDao.addBook(book);}public int updateBook(Book book) {return bookDao.updateBook(book);}public  int deleteBookById(Integer id) {return bookDao.deleteBookById(id);}public Book getBookById(Integer id) {return bookDao.getBookById(id);}public List<Book> getAllBooks() {return bookDao.getAllBooks();}
}

Controller:

@RestController
public class BookController {@AutowiredBookService bookService;@GetMapping("/bookOps")public void bookOps() {Book b1 = new Book();b1.setId(4);b1.setName("西厢记");b1.setAuthor("王实甫");int i = bookService.addBook(b1);System.out.println("addBook>>>" + i);Book b2 = new Book();b2.setId(1);b2.setName("朝花夕拾");b2.setAuthor("鲁迅");int updateBook = bookService.updateBook(b2);System.out.println("updateBook>>>"+updateBook);Book b3 = bookService.getBookById(1);System.out.println("getBookById>>>"+b3);int delete = bookService.deleteBookById(2);System.out.println("deleteBookById>>>"+delete);List<Book> allBooks = bookService.getAllBooks();System.out.println("getAllBooks>>>"+allBooks);}
}

在这里我遇到了很多坑,首先是初始化问题。记住一定要把类的创建放在autowired(自动装箱)后面,否则一直会报错null.

整合MyBatis

MyBatis是一款优秀的持久层框架,支持定制化SQL,存储过程以及高级映射。MyBatis几乎避免所有的JDBC代码手动设置参数以及获取结果集。在传统的SSM框架整合中,使用它需要大量的配置,而在Spring Boot提供了自动化配置方案,可以做到开箱即用。步骤如下:

首先展现项目文件目录情况:

添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency>

数据库和表,实体类以及application.properties配置见上文jdbcTemplate一节。
创建数据库访问层
BookMapper:

@Mapper
public interface BookMapper {int addBook(Book book);int deleteBookById(Integer id);int updateBookById(Book book);Book getBookById(Integer id);List<Book> getAllBooks();
}

@Mapper注解,表示这是MyBatis中的接口,这种方式在每个Mapper添加注解。
BookMapper.xml:
BookMapper接口中的每一个方法都在BookMapper.xml实现了。
#{}用来替代接口中的参数,实体类中的属性可以直接通过#{实体类属性名}获取。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace ="com.example.demo.testMybatis.mapper.BookMapper"><insert id ="addBook" parameterType="com.example.demo.testMybatis.model.Book">insert into book (name,author) values (#{name},#{author})</insert><delete id="deleteBookById" parameterType="int">delete from book where id = #{id}</delete><update id="updateBookById" parameterType="com.example.demo.testMybatis.model.Book">update book set name = #{name},author = #{author} where id = #{id}</update><select id="getBookById" parameterType="int" resultType="com.example.demo.testMybatis.model.Book">select  * from book where id = #{id}</select><select id="getAllBooks" resultType="com.example.demo.testMybatis.model.Book">select * from book</select>
</mapper>

BookService.java:

@Service
public class BookService {@Autowired(required = false)BookMapper bookMapper;public int addBook(Book book) {return bookMapper.addBook(book);}public int updateBook(Book book) {return bookMapper.updateBookById(book);}public int deleteBookById(Integer id) {return bookMapper.deleteBookById(id);}public Book getBookById(Integer id) {return bookMapper.getBookById(id);}public List<Book> getAllBooks() {return bookMapper.getAllBooks();}
}

BookController.java:

@RestController
public class BookController {@AutowiredBookService bookService;@GetMapping("/bookOps")public void bookOps() {Book b1 = new Book();b1.setName("西厢记");b1.setAuthor("王实甫");int i = bookService.addBook(b1);System.out.println("addBook>>>" + i);Book b2 = new Book();b2.setId(1);b2.setName("朝花夕拾");b2.setAuthor("鲁迅");int updateBook = bookService.updateBook(b2);System.out.println("updateBook>>>"+updateBook);Book b3 = bookService.getBookById(1);System.out.println("getBookById>>>"+b3);int delete = bookService.deleteBookById(2);System.out.println("deleteBookById>>>"+delete);List<Book> allBooks = bookService.getAllBooks();System.out.println("getAllBooks>>>"+allBooks);}
}

配置pom.xml文件:
在Maven工程中,xml配置文件建议写在resources目录,但我们的xml是写在了Mapper包下,故需要指明资源文件位置:

<build>
<resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource><resource><directory>src/main/resources</directory></resource></resources></build>

当然可以把xml放在resources包中,并把文件夹名改为mapper,然后在application.properties配置:

# 配置mybatis
mybatis.mapper-locations=classpath:/mapper/*.xml

输入8080/bookOps,便可以在控制台打印出日志:

整合Spring Data JPA

JPA是一种ORM规范。Spring Data 是Spring的一个子项目,致力于简化数据库访问。通过规范的方法名称来分析开发者的意图,进而减少数据库访问层的代码量。Spring Data 不仅支持关系型数据库,也支持非关系型数据库。
Spring Boot 整合Spring Data JPA的步骤如下:

先建一个数据库:

create database  jpa default character set utf8;

创建数据库即可不用建表。
添加依赖:

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.1</version></dependency><dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>

数据库配置:在application.properties配置数据库基本信息
1-4行是数据库基本信息配置,5-8行是JPA相关配置。第5行表示是否在控制台打印生成的SQL。第6行表示对JPA对应的数据库为MySQL,第7行表示项目启动时实时更新数据库中的表。第8行表示使用的数据库方言。

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql:///jpa
spring.datasource.username=root
spring.datasource.password=qazwsx123
spring.jpa.show-sql=true
spring.jpa.database=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

创建实体:
Book.java:

import javax.persistence.*;@Entity(name ="jpabook")
public class Book {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;@Column(name = "book_name",nullable = false)private String name;private String author;private Float price;@Transientprivate String description;//省略getter/setter@Overridepublic String toString() {return "Book{" +"id=" + id +", name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +", description='" + description + '\'' +'}';}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public Float getPrice() {return price;}public void setPrice(Float price) {this.price = price;}
}

@Entity注解表示该类是一个实体类,项目启动时生成一张表,表的名称就是name值。(如果不配置name,默认为类名)
所有的实体类都要有主键,@Id表示该属性是一个主键,@GeneratedValue表示主键自动生成,strategy表示主键的生成策略。
默认情况下,生成的表字段名称就是实体类的属性。
@Transient注解表示在生成数据库表的时候不生成对应的字段。
创建BookDao接口:

BookDao.java:

public interface BookDao extends JpaRepository<Book,Integer> {List<Book> getBooksByAuthorStartingWith(String author);List<Book> getBooksByPriceGreaterThan(Float price);@Query(value = "select * from t_book where id=(select max(id) from t_book)",nativeQuery = true)Book getMaxIdBook();@Query("select b from book b where b.id>:id and b.author=:author")List<Book> getBookByIdAndAuthor(@Param("author") String author, @Param("id") Integer id);@Query("select b from book b where b.id<?2 and b.name like %?1%")List<Book> getBooksByIdAndName(String name, Integer id);
}

自定义BookDao继承自JpaRepository.其提供了一些基本的数据操作方法,有基本的增删改查、分页查询、排序查询等。
在JPA中,只要方法的定义符合既定规范,Spring Data就能分析出开发者的意图,从而避免开发者定义SQL。(既定规范,就是一定的方法命名规则,支持的命名规则如下:)

创建BookService:

@Service
public class BookService {@AutowiredBookDao bookDao;public void addBook(Book book) {bookDao.save(book);}public Page<Book> getBookByPage(Pageable pageable) {return bookDao.findAll(pageable);}public List<Book> getBooksByAuthorStartingWith(String author){return bookDao.getBooksByAuthorStartingWith(author);}public List<Book> getBooksByPriceGreaterThan(Float price){return bookDao.getBooksByPriceGreaterThan(price);}public Book getMaxIdBook(){return bookDao.getMaxIdBook();}public List<Book> getBookByIdAndAuthor(String author, Integer id){return bookDao.getBookByIdAndAuthor(author, id);}public List<Book> getBooksByIdAndName(String name, Integer id){return bookDao.getBooksByIdAndName(name, id);}
}

在addBook中save方法将对象数据保存到数据库,save方法是由JpaRepository接口提供的。
在Page 是一个分页查询,使用findAll。

创建BookController,实现对数据的测试:

@RestController
public class BookController {@AutowiredBookService bookService;@GetMapping("/findAll")public void findAll() {PageRequest pageable = PageRequest.of(2, 3);Page<Book> page = bookService.getBookByPage(pageable);System.out.println("总页数:"+page.getTotalPages());System.out.println("总记录数:"+page.getTotalElements());System.out.println("查询结果:"+page.getContent());System.out.println("当前页数:"+(page.getNumber()+1));System.out.println("当前页记录数:"+page.getNumberOfElements());System.out.println("每页记录数:"+page.getSize());}@GetMapping("/search")public void search() {List<Book> bs1 = bookService.getBookByIdAndAuthor("鲁迅", 7);List<Book> bs2 = bookService.getBooksByAuthorStartingWith("吴");List<Book> bs3 = bookService.getBooksByIdAndName("西", 8);List<Book> bs4 = bookService.getBooksByPriceGreaterThan(30F);Book b = bookService.getMaxIdBook();System.out.println("bs1:"+bs1);System.out.println("bs2:"+bs2);System.out.println("bs3:"+bs3);System.out.println("bs4:"+bs4);System.out.println("b:"+b);}@GetMapping("/save")public void save() {Book book = new Book();book.setAuthor("鲁迅");book.setName("呐喊");book.setPrice(23F);bookService.addBook(book);}
}

调用8080/save,数据库就用显示相应的数据,同时使用8080/search查看数据。

多数据源

所谓多数据源,就是JavaEE项目中采用了不同数据库实例中的多个库,或者同一个数据库实例中多个不同的库。一般来说,采用MyCat等分布式数据库中间件是比较好的解决方案,这样可以把数据库读写分离,分库分表,备份等操作。
对于以上的操作不再讲述多数据源操作方法。

[Spring Boot 2]整合持久层技术相关推荐

  1. springboot整合持久层技术

    springboot整合持久层技术 整合jdbcTemplate 1.依赖导入 <?xml version="1.0" encoding="UTF-8"? ...

  2. 【SpringBoot】SpringBoot——整合持久层技术

    文章目录 5. 整合持久层技术 5.1 整合JdbcTemplate 5.2 整合MyBatis 5.3 Spring Data JPA 5.3.1 JPA.Spring Data.Spring Da ...

  3. springboot整合持久层技术(mysql驱动问题)

    java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more tha ...

  4. mybatis generator 中文注释_[SpringBoot2.X] 23- 整合持久层技术 -MyBatis - 配置

    整合MyBatis 1搭建项目环境 1.1.1创建项目--略 11.2修改POM文件,添加相关依赖 <dependency><groupId>org.springframewo ...

  5. Spring boot 三层框架dao层、service层、controller层+实体model层

    Spring boot 三层框架dao层.service层.controller层+实体model层 model层 dao层 service层 controller层 首先创建一个springboot ...

  6. spring boot mybatis 整合_Spring、MyBatis和SpringMVC的整合

    SSM框架整合的知识. 不用maven,为什么呢?主要是帮助更好的理解有哪些包,这样更加透彻.当然了,使用maven会更方便一点. 1 jar包管理 2 整合思路 spring在进行管理时,是很有条理 ...

  7. Spring boot Mybatis 整合(完整版)

    Spring boot Mybatis 整合(完整版) 更多干货 SpringBoot系列目录 正题 本项目使用的环境: 开发工具:Intellij IDEA 2017.1.3 springboot: ...

  8. spring boot 学习(二)spring boot 框架整合 thymeleaf

    spring boot 框架整合 thymeleaf spring boot 的官方文档中建议开发者使用模板引擎,避免使用 JSP.因为若一定要使用 JSP 将无法使用. 注意:本文主要参考学习了大神 ...

  9. 关于Spring Boot WebSocket整合以及nginx配置详解

    这篇文章主要给大家介绍了关于Spring Boot WebSocket整合以及nginx配置的相关资料,文中通过示例代码给大家介绍的非常详细,相信对大家的学习或者工作具有一定的参考学习价值,需要的朋友 ...

最新文章

  1. (2)PyCharm开发Flash项目之蓝图构建
  2. 在linux下实现mysql自动备份数据
  3. 微信小程序 Unexpected end of JSON input
  4. PyTorch 1.0 中文官方教程:什么是 PyTorch
  5. armgcc交叉编译的文件无法运行_[阿里巴巴(校招/社招)] 虚拟机与编译器团队招人啦~ (JVM / GCC / LLVM 方向)...
  6. 综合评价指标权重方法汇总
  7. 龙格-库塔(Runge-Kutta)
  8. PS 使用批处理来另存为图片
  9. 蓝桥杯单片机(十一)PCF8591(A/D转换)
  10. QT自定义控件插件学习笔记
  11. 手摸手写一个互联网黑话生成器
  12. 九度 题目1335:闯迷宫 题目1365:贝多芬第九交响曲
  13. ubuntu18.04程序开机自启动
  14. Algorithm Gossp (18) 最大公因数、最小公倍数、因式分解
  15. js/JavaScript防抖处理
  16. 程序员『天梯排行榜』
  17. 免费学plc的手机app_手机APP操控PLC
  18. OpenGL 半透明效果的实现(混合)、雾效果 和 圆滑(抗锯齿)
  19. 程序员如何提高10%的效率2
  20. linux zynq usb0,Ubuntu下ZedBoard USB-Jtag驱动安装及双核调试

热门文章

  1. 笔记本电脑拆解时笔记本电脑的螺丝有了磁力怎么办?哪些注意事项?
  2. android 蓝牙版本兼容,Android蓝牙4.0 版本兼容性问题
  3. JS中2种定时器的使用及清除
  4. 苹果研发者账号增加受信手机号
  5. hashMap的容量(capacity)为什么必须是是2的n次方
  6. Unity shaderGraph 学习记录——玻璃折射
  7. python如何切换windows窗口_python – Windows 7:如何把窗口带到前面,无论其他窗口有什么重点?...
  8. 在JS中获取父标签的id
  9. 自然语言菜鸟学习笔记(二)
  10. redis 序列化对象问题