首先,我们需要在项目的pom.xml中引入mybatis的依赖和Druid连接池依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.1.RELEASEversion>
<relativePath/>
parent>
<groupId>com.LirsgroupId>
<artifactId>SpringartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>Springname>
<description>SpringBoot学习框架description>
<properties>
<java.version>1.8java.version>
<mysql.version>5.0.8mysql.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.1version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.20version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
Druid是一个关系型数据库连接池,是阿里巴巴的一个开源项目,
地址:https://github.com/alibaba/druid
Druid不但提供连接池的功能,还提供监控功能,可以实时查看数据库连接池和SQL查询的工作情况。
这个我之前也没用过。正好趁这次机会顺便学了。
之后就是修改配置文件application.yml
server:
port: 8081#修改tomcat端口
servlet:
context-path: /Spring#修改访问路径
spring:
datasource:
druid:
#数据库访问配置,我本地的mysql端口号是3307
url: jdbc:mysql://localhost:3307/spring?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
username: root
password: password
#连接池配置
initial-size: 5 #默认连接数
min-idle: 5 #最小连接数
#max-idle: 10 已经弃用
max-wait: 30000 #连接等待超时时间
time-between-eviction-runs-millis: 60000 #配置检测可以关闭的空间连接间隔时间
min-eviction-idle-time-millis: 30000 #连接在池中最小生存时间
validationQuery: select 1 #用于验证数据库连接是否有效 oracle为select 1 from dual
test-while-idle: true
test-on-borrow: false
test-on-return: false
#打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
max-open-prepared-statements: 20
max-pool-prepared-statement-per-connection-size: 20
# 配置监控统计拦截的filters, 去掉后监控界面sql无法统计, 'wall'用于防火墙
filters: stat,wall
# Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔
#aop-patterns: com.springboot.servie.* 暂时用不上,先注释
# WebStatFilter配置 用于url统计 这点之后做补充学习
web-stat-filter:
enabled: true
# 添加过滤规则
url-pattern: /*
# 忽略过滤的格式
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
# StatViewServlet配置 用于提供展示监控信息的html页面、JSON API
stat-view-servlet:
enabled: true
# 访问路径为/druid时,跳转到StatViewServlet
url-pattern: /druid/*
# 是否能够重置数据
reset-enable: false
# 监控控制台需要账号密码才能访问
login-username: admin
login-password: password
# IP白名单
# allow: 127.0.0.1
# IP黑名单(共同存在时,deny优先于allow)
# deny: 192.168.1.218
# 配置StatFilter 打开监控统计功能
filter:
stat:
log-slow-sql: true
记录两个配置application.yml时犯的错:
initial-size:5 #错误的原因,冒号之后少了一个空格
initial-size: 5 #这是正确的
spring:
datasource:
druid:
web-stat-filter:
enabled: true
# StatViewServlet配置 用于提供展示监控信息的html页面、JSON API
stat-view-servlet:
enabled: true
#这里表示的配置信息:spring.datasource.druid.stat-view-servlet
上面是正确的
spring:
datasource:
druid:
web-stat-filter:
enabled: true
# StatViewServlet配置 用于提供展示监控信息的html页面、JSON API
stat-view-servlet:
enabled: true
#这里的错误在于stat-view-servlet前多了两个空格
#导致这里的配置信息变成了spring.datasource.druid.web-stat-filter.stat-view-servlet
完成配置后访问http://localhost:端口号/项目名/druid
输入账号密码之后就可以看到Durid的监控页面了。功能还是满齐全的。
Durid暂且放在一边
之后我们在数据库中创建一张表并添加一些数据
CREATE TABLE `tb_user` (
`id` varchar(255) NOT NULL,
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL,
`sex` varchar(3) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES ('1', 'admin', '123', 'f', '18');
INSERT INTO `user` VALUES ('2', 'user', '123', 'f', '18');
INSERT INTO `user` VALUES ('3', 'zhangsan', '123', 'f', '20');
创建对应的实体类
public class User {
private String id;
private String username;
private String passowrd;
private String sex;
private int age;
//对应的getter、setter省略
创建对应的Mapper:
这里有两种方式:
一、注解方式:
//mapper注解的作用在于让spring在初始化时为我们创建一个实体类,
//不然如果我们使用@Autowired的时候,Spring会因为找不到对应的实体类初始化而报错
@Mapper
@Repository
public interface UserMapper {
@Insert("insert into tb_user (id,username,password,sex,age) values(#{id},#{username},#{password},#{sex},#{ages})")
int save(User user);
@Update("update tb_user set username = #{username},password=#{password},#sex={sex},#{age} where id = #{id}")
int update(User user);
@Delete("delete from tb_user where id = #{id}")
int deleteById(String id);
@Select("select * from tb_user where id = #{id}")
User selectById(String id);
@Select("select * from tb_user")
List<User> selectAll();
}
因为我这里没有什么实际的业务,所以就去掉了service层的业务处理,只是简单的将数据返回到前端。
Controller层就以简单的返回结果作为测试
@RequestMapping("/getAll")
public List<User> getAll(){
return userMapper.selectAll();
}
在浏览器输入url之后就可以得到数据了
druid中也可以看到对刚才sql语句的监控情况
二、xml配置方式:
同样以刚才的mapper为例子
@Repository
@Mapper
public interface UserMapper {
int save(User user);
int update(User user);
int deleteById(String id
User selectById(String id
List<User> selectAll();
}
在resource目录下创建一个mapeer目录,并且放入xml文件
并且在application.yml中还需要添加xml路径
mybatis:
mapper-locations: classpath:mapper/*.xml
mapper.xml中的配置
<mapper namespace="com.Lirs.Spring.Mapper.UserMapper">
<select id="selectAll" resultType="com.Lirs.Spring.Model.User">
select * from tb_user
select>
mapper>
注解方式如果想使用动态sql,则需要额外创建一个SQL类
public class UserMapperProvider {
public static String selectById(final String id){
return new SQL(){{
SELECT("*");
FROM("tb_user");
if(id != null){
WHERE("id = #{id}");
}
}}.toString();
}
}
Mapper接口
@SelectProvider(type = UserMapperProvider.class,method = "selectById")
User selectById(String id);
为什么Mapper接口需要返回的是一个User对象,而SQL类中返回的却是一个String
原因在于SQL类的父类中对toString()方法进行了重写
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sql().sql(sb);
return sb.toString();
}
//sql()返回一个内部类对象SqlStatement
private final SQLStatement sql = new SQLStatement();
private SQLStatement sql() {
return sql;
}
//sql(sql)返回String
public String sql(Appendable a) {
SafeAppendable builder = new SafeAppendable(a);
if (statementType == null) {
return null;
}
String answer;
switch (statementType) {
case DELETE:
answer = deleteSQL(builder);
break;
case INSERT:
answer = insertSQL(builder);
break;
case SELECT:
answer = selectSQL(builder);
break;
case UPDATE:
answer = updateSQL(builder);
break;
default:
answer = null;
}
return answer;
}
其实原理就是在Spring实例化mapper时,其实是创建了一个mapper的代理对象,而代理对象内真正的方法是Provider中的方法。实际执行的也是这个方法。所以才会出现Mapper中定义的返回值是User,而SQL类中返回值是String。
注意: 如果你需要返回一个对象,那么你的mapper接口中返回值必须是对象,不能是String,如果返回值是String,那么默认只会返回查询到的记录第一列的内容
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
之后就可以直接使用Spring去帮我们控制jdbcTemplate
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
private static final int[] TYPE = {Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.INTEGER};
@Override
public int save(User user) {
String sql = "insert into tb_user (id,username,password,sex,age) values(?,?,?,?,?)";
Object agrs[] = {user.getId(),user.getUsername(),user.getPassowrd(),user.getSex(),user.getAge()};
return jdbcTemplate.update(sql,agrs,TYPE);
}
@Override
public int update(User user) {
String sql = "update tb_user set username = ? ,password = ? ,sex = ?, age = ? where id = '1'";
Object args[] = {user.getUsername(),user.getPassowrd(),user.getSex(),user.getAge()};
int argsType[] = {Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.INTEGER};
return jdbcTemplate.update(sql,args,argsType);
}
@Override
public int deleteById(String id) {
String sql = "delete from tb_user where id = ?";
int argsType[] = {Types.VARCHAR};
Object args[] = {id};
return jdbcTemplate.update(sql,args,argsType);
}
@Override
public User selectById(String id) {
String sql = "select * from tb_user where id = ?";
Object args[] = {id};
int argsTypes[] = {Types.VARCHAR};
List<User> list = jdbcTemplate.query(sql,args,new UserMapper());
if(list != null && !list.isEmpty()){
return list.get(0);
}
return null;
}
@Override
public List selectAll() {
String sql = "select * from tb_user";
List<User> users = jdbcTemplate.query(sql,new UserMapper());
return users;
/**
*还可以使用这种写法。
*/
//return jdbcTemplate.queryForList(sql);
}
}
class UserMapper implements RowMapper<User>{
@Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user = new User();
user.setId(resultSet.getString("id"));
user.setPassowrd(resultSet.getString("password"));
user.setUsername(resultSet.getString("username"));
user.setSex(resultSet.getString("sex"));
user.setAge(resultSet.getInt("age"));
return user;
}
}
返回集合有两种方式,一种是创建一个RowMapper的子类,手动的去给集合中的对象赋值。另一个则是通过queryForList方法直接返回一个List集合,不过要注意,queryForList返回的类型是List
不过我们可以通过不指定泛型的方式直接取得一个List集合
//这里是dao层
public List selectAll() {
String sql = "select * from tb_user";
return jdbcTemplate.queryForList(sql);
}
//这里是controller层
@RequestMapping("/selectUseJDBC")
public List<User> selectUseJDBC
return userDao.selectAll();
}
这样可以成功的原因就在于java对泛型的检测只在编码阶段,这样做相当于欺骗了编译器,告诉他List里面存放的是一个Object,实际上是一个Map。然后再经由SpringMvc的@ResponseBody注解将List中的对象映射成json格式的字符串发送出去。就可以神不知鬼不觉的将一个List
大功告成!非常欢迎大家讨论文章的内容以及指出文章中不足或错误的地方。感谢!