一. 常见的数据库
在项目开发中,数据库的访问是必不可少的
ORM持久化技术 | 模板类 |
---|---|
JDBC(JdbcTemplate) | org.springframework.jdbc.core.JdbcTemplate |
JPA | org.springfrmaework.orm.jpa.JpaTemplate |
IBatis(MyBatis) | org.springframework.orm.ibatis.SqlMapClientTemplate |
1.JdbcTemplate
JdbcTemplate是Spring对JDBC的模板封装,提供了一套JDBC模板,能够让我们写持久层代码时减少冗余代码,简化JDBC代码,使代码更加简洁。Spring Boot默认支持JdbcTemplate(无需配置)。JdbcTemplate在实际开发中一般不会使用,通常都是使用MyBatis、Hibernate等更加成熟、优秀的数据持久层框架。
2.JPA
JPA全称是Java Persistence API,即java持久化API,是sun公司推出的一套基于ORM的规范
,内部由一系列的接口和抽象类构成。
- Hibernate
JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。 - Spring Data JPA
Spring Data JPA是Spring提供的一套对JPA操作更加高级的封装,是在JPA规范下的专门用来进行数据持久化的解决方案。
3.MyBatis
MyBatis是目前Java平台最为流行的ORM框架
4. 优缺点比较
JDBC直接操作:比较古老,开发起来太麻烦,
JdbcTemplate:spring在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中。Spring-data-jpa引入的时候,JdbcTemplate必然会被引入的。
Spring-data-jpa: 使用hibernate作为实现,特点就是所有的 SQL 都用 Java 代码来生成,不用跳出程序去写(看) SQL ,有着编程的完整性,缺点是处理复杂业务时,灵活度差。
Mybatis插件:比较时髦,比较适合sql复杂,或者对性能要求高的应用,因为sql都是自己写的。
二. MyBatis使用
SpringBoot 整合 Mybatis 有两种常用的方式,一种就是我们常见的 xml 的方式 ,还有一种是全注解的方式。我觉得这两者没有谁比谁好,在 SQL 语句不太长的情况下,我觉得全注解的方式一定是比较清晰简洁的。但是,复杂的 SQL 确实不太适合和代码写在一起。
1.创建数据表
CREATE TABLE `user` (
`id` int(13) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(33) DEFAULT NULL COMMENT '姓名',
`age` int(3) DEFAULT NULL COMMENT '年龄',
`money` double DEFAULT NULL COMMENT '账户余额',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
2.配置 pom 文件中的相关依赖
org.mybatis.spring.boot
mybatis-spring-boot-starter
3.3.0
3.配置 application.properties
#mybatis依赖对应实体类的包名,定义所有操作类的别名所在包
mybatis.type-aliases-package=com.peng.springbootdemo.dao
4.创建用户类 Bean
public class User {
private int id;
private String name;
private int age;
private double money;
...
此处省略getter、setter以及 toString方法
}
5.全注解的方式
全注解的方式,这种方式和后面提到的 xml 的方式的区别仅仅在于 一个将 sql 语句写在 java 代码中,一个写在 xml 配置文件中。全注方式解转换成 xml 方式仅需做一点点改变即可,我在后面会提到。
项目结构
1. Dao 层开发
UserDao.java
@Mapper
public interface UserDao {
/**
* 通过名字查询用户信息
*/
@Select("SELECT * FROM user WHERE name = #{name}")
User findUserByName(@Param("name") String name);
/**
* 查询所有用户信息
*/
@Select("SELECT * FROM user")
List findAllUser();
/**
* 插入用户信息
*/
@Insert("INSERT INTO user(name, age,money) VALUES(#{name}, #{age}, #{money})")
void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("money") Double money);
/**
* 根据 id 更新用户信息
*/
@Update("UPDATE user SET name = #{name},age = #{age},money= #{money} WHERE id = #{id}")
void updateUser(@Param("name") String name, @Param("age") Integer age, @Param("money") Double money,
@Param("id") int id);
/**
* 根据 id 删除用户信息
*/
@Delete("DELETE from user WHERE id = #{id}")
void deleteUser(@Param("id") int id);
}
2 service 层
@Service
public class UserService {
@Autowired
private UserDao userDao;
/**
* 根据名字查找用户
*/
public User selectUserByName(String name) {
return userDao.findUserByName(name);
}
/**
* 查找所有用户
*/
public List selectAllUser() {
return userDao.findAllUser();
}
/**
* 插入两个用户
*/
public void insertService() {
userDao.insertUser("SnailClimb", 22, 3000.0);
userDao.insertUser("Daisy", 19, 3000.0);
}
/**
* 根据id 删除用户
*/
public void deleteService(int id) {
userDao.deleteUser(id);
}
/**
* 模拟事务。由于加上了 @Transactional注解,如果转账中途出了意外 SnailClimb 和 Daisy 的钱都不会改变。
*/
@Transactional
public void changemoney() {
userDao.updateUser("SnailClimb", 22, 2000.0, 3);
// 模拟转账过程中可能遇到的意外状况
int temp = 1 / 0;
userDao.updateUser("Daisy", 19, 4000.0, 4);
}
}
3. Controller 层
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/query")
public User testQuery() {
return userService.selectUserByName("Daisy");
}
@RequestMapping("/insert")
public List testInsert() {
userService.insertService();
return userService.selectAllUser();
}
@RequestMapping("/changemoney")
public List testchangemoney() {
userService.changemoney();
return userService.selectAllUser();
}
@RequestMapping("/delete")
public String testDelete() {
userService.deleteService(3);
return "OK";
}
}
4. 启动类
//此注解表示SpringBoot启动类
@SpringBootApplication
// 此注解表示动态扫描DAO接口所在包,实际上不加下面这条语句也可以找到
@MapperScan("top.snailclimb.dao")
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
5. 简单测试
上述代码经过测试都没问题,这里贴一下根据姓名查询的测试的结果。
6.xml 的方式
项目结构:
1. Dao 层的改动
我这里只演示一个根据姓名找人的方法。
UserDao.java
@Mapper
public interface UserDao {
/**
* 通过名字查询用户信息
*/
User findUserByName(String name);
}
UserMapper.xml
2. 配置文件的改动
application.properties配置文件中加入下面这句话:
mybatis.mapper-locations=classpath:mapper/*.xml
7.Mybatis插件
- Mybatis-Generator
Mybatis-Generator是Mybatis提供的一个便捷型插件,自动可以为项目生产对应的实体类,Mapper,dao层。 - mybatis-plus
mybatis可以直接在xml中通过SQL语句操作数据库,很是灵活。但正其操作都要通过SQL语句进行,就必须写大量的xml文件,很是麻烦。mybatis-plus就很好的解决了这个问题。
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。这是官方给的定义,关于mybatis-plus的更多介绍及特性,可以参考mybatis-plus官网。那么它是怎么增强的呢?其实就是它已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA。
三. 数据库连接池
使用JDBC技术的时候,每次用完了,都会将连接关闭;等到下一次再用的时候,都得将数据库连接再打开。实际上,数据库链接资源是十分宝贵的,我们在小型的项目中还看不出来,在高并发的项目中,这样频繁的打开和关闭数据库链接是对服务器的一种摧残,十分影响效率。
所谓的数据库连接池技术,就是用来分配,管理,释放数据库连接的,数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
常用的主流开源数据库连接池有C3P0、DBCP、Tomcat Jdbc Pool、BoneCP、Druid等。
Spring Boot 默认使用的连接池是 HikariCP ,当在在依赖中引入了
spring-boot-starter-jdbc
或者 spring-boot-starter-data-jpa
,且application.properties中没有配置spring.datasource.type 为其他的DataSource时。Spring Boot 会默认使用HiKariCP,如果需要使用其他的连接池,例如druid连接池,则需要引入 druid 依赖:
com.alibaba
druid-spring-boot-starter
1.1.10
并且在application.properties中配置
#表明使用Druid连接池
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
配置连接池的相关属性,这些参数根据自己的需要灵活配置即可:
#初始化时建立物理连接的个数。
spring.datasource.druid.initial-size=5
#最大连接池数量
spring.datasource.druid.max-active=20
#最小连接池数量
spring.datasource.druid.min-idle=5
#获取连接时最大等待时间,单位毫秒
spring.datasource.druid.max-wait=3000
#是否缓存preparedStatement,也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
spring.datasource.druid.pool-prepared-statements=false
#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
spring.datasource.druid.max-open-prepared-statements= -1
#配置检测可以关闭的空闲连接间隔时间
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 配置连接在池中的最小生存时间
spring.datasource.druid.min-evictable-idle-time-millis= 300000
spring.datasource.druid.max-evictable-idle-time-millis= 400000
Druid是阿里巴巴的一个开源项目,号称为监控而生的数据库连接池,在功能、性能、扩展性方面都超过其他例如DBCP、C3P0、BoneCP、Proxool、JBoss DataSource等连接池,而且Druid已经在阿里巴巴部署了超过600个应用,通过了极为严格的考验,这才收获了大家的青睐!