Marco's Java【SpringBoot进阶(四) 之 启用Druid数据源分别集成JdbcTemplate及Mybatis】

前言

上一节我们专门针对于SpringBoot的数据源的使用做了完整的讲解,尤其是对DruidDataSource的使用做了详细的分析,其实上节我们手写的DruidAutoConfig配置类,Alibaba官方已经给到了相应的启动jar包,包含这个配置类,根本不需要我们自己去写… 哈哈,并不是不想提前告诉你们,毕竟了解实现的原理最重要嘛!
那么本节呢,咱们换一种使用方式,并集成JdbcTemplate来尝试获取数据库中的数据吧!

使用启动器配置Druid的数据源

我们先在pom.xml中加入Druid的 “启动装置”
在这里插入图片描述
重新Update我们的项目之后看,在Maven Dependencies可以找到刚刚下好的druid-spring-boot-starter-1.1.18.jar
在这里插入图片描述
欸?好像发现一个很熟悉的类,DruidDataSourceAutoConfigure不正是我们上节手写的DruidAutoConfigure配置类吗?好奇心驱使着我打开了DruidDataSourceAutoConfigure的源码
在这里插入图片描述
第一眼就看到了作者lihengming,我发现阿里的大佬儿们,完成一个项目之后都会把自己邮箱给备注在上面,哈哈。回到正题,这第一页就这几行代码,我们先看注解部分,源码中也在方法上添加了@Bean(initMethod = "init"),这个属性用于在bean初始化时指定执行方法,主要是为了替代继承 InitializingBean接口。
类上的注解不用我解释,相信大家也应该有经验知道是啥意思了,不难看出我们配置类是必须依赖DruidDataSource数据源的,咱们点开DruidStatProperties可以看到有哪些druid属性可以在配置文件中配置。
另外@ConditionalOnMissingBean指的就是当IoC容器中不存在DataSource数据源时,才会执行。
在这里插入图片描述
其他的就没啥好说的啦,咱们回过头来看看下面这个方法

public DataSource dataSource() {
     LOGGER.info("Init DruidDataSource");
     return new DruidDataSourceWrapper();
 }

该方法就只做了一件事情,返回了DruidDataSourceWrapper对象?根据这个类的名字不难推断这应该是一个DruidDataSource的包装类,那么我们接着点开这个类的源码瞧瞧。

@ConfigurationProperties("spring.datasource.druid")
class DruidDataSourceWrapper extends DruidDataSource implements InitializingBean {
    @Autowired
    //自动装配DataSourceProperties文件类
    private DataSourceProperties basicProperties;

    @Override
    public void afterPropertiesSet() throws Exception {
        //if not found prefix 'spring.datasource.druid' jdbc properties ,'spring.datasource' prefix jdbc properties will be used.
        //当我们在配置文件中没有找到以'spring.datasource.druid'开头的"头信息"时
        //默认加载'spring.datasource'中的配置信息
        if (super.getUsername() == null) {
            super.setUsername(basicProperties.determineUsername());
        }
        if (super.getPassword() == null) {
            super.setPassword(basicProperties.determinePassword());
        }
        if (super.getUrl() == null) {
            super.setUrl(basicProperties.determineUrl());
        }
        if (super.getDriverClassName() == null) {
            super.setDriverClassName(basicProperties.getDriverClassName());
        }
    }

    @Autowired(required = false)
    public void autoAddFilters(List<Filter> filters){
    	//将filter放入过滤器链中,这里的filter中应当存在WebStatFilter
        super.filters.addAll(filters);
    }
}

从这里可以看出,DruidDataSourceWrapper确实就是将DruidDataSource稍微包装了一下,当我们在配置文件中没有找到以spring.datasource.druid开头的"头信息"的时侯,SpringBoot默认会去加载默认会去加载spring.datasource中的配置信息,咱们之前也在配置类上定义过spring.datasource.druid对吧?另外除了数据源配置的4大要素不能为空以外,其他的信息默认是可以不用配置的。
在这里我们就不再继续深入研究里面的东西了,底层和我们上节手写的代码是差不多的,只不过细节方面会做的更好。

接下来就是配置yml文件的配置,其实也和上节咱们写的配置差不多,只不过在druid的starter包中将数据源的一些基本配置要素都放进了spring.datasource.druid中,具体可以参考配置文件类DruidStatProperties

spring:
  datasource:
    druid:
      url: jdbc:mysql://127.0.0.1:3306/user
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: zcq774798947
      max-active: 20 #最大活跃连接量
      initial-size: 5 #初始连接数量
      max-wait: 5000 #最大等待量
      validation-query: select 'x' #配合定期检查的sql,每隔一段时间检查sql是否正常
      keep-alive: true #定期检查开启
      enable: true #启用,默认为false
      ## 监控页面的配置
      filters: stat
      stat-view-servlet: 
        login-username: root
        login-password: zcq774798947
        allow: 
        deny: 
        enabled: true  #启用,默认为false
        url-pattern: /druid/*
      web-stat-filter:
        exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
        enabled: true #启用,默认为false
        profile-enable: true
        session-stat-enable: true
        principal-session-name: USER_SESSION
        principal-cookie-name: USER_COOKIE
        url-pattern: /druid/*        

配置完了,咱们再来测试下咯。好像也没啥问题。
在这里插入图片描述

启用Druid数据源集成JdbcTemplate

接下来咱们集成JdbcTemplate,看看能否使用DruidDataSource数据源操作数据库。
大家还记得在讲解SpringBoot启动原理的那一章提到的存放118名 “大将” 的文件spirng.factories吗?咱们来点开看看… 发现我们JdbcTemplateAutoConfiguration也在这118名 “大将” 中,而且我们也到导入了spring-jdbc的jar包
在这里插入图片描述
那么根据我们以前的经验,我猜想JdbcTemplate在SpringBoot中是可以直接使用的,到底是不是这样呢?我们来测试看看吧~

package com.marco;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootDatasourceApplicationTests {

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@Test
	public void contextLoads() {
		Integer count = jdbcTemplate.queryForObject("select (1) from userinfo", Integer.class);
		System.out.println(count);
	}
}

我靠!!怎么报了这么长的错误,抛出的异常说The server time zone value '?й???׼ʱ?' is unrecognized,还有乱码?
在这里插入图片描述

解决异常com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value ‘xxxx?’ is unrecognized or represents more than one time zone

既然问题抛出来了,咱们就要解决吗,根据异常显示,大概可以猜出来是timezone的问题,You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.根据抛出的异常后面的内容,我们可以略加分析一下,这句英文的大意是 “如果你想使用timezone,必须定义更加详细确切的timezone时区”,我们想想到底哪个地方用了timezone啊?
记性好的朋友应该还记得我在上节 Marco’s Java【SpringBoot进阶(三) 之 SpringBoot数据源配置和自动管理】 有提到因为我的mysql驱动mysql-connector-java是6.0以上的版本,因此需要指定时区serverTimezone。
如果大家碰到了这个问题,在spring.datasource.druid中的url后面加上serverTimezone=UTC(世界标准时间)就可以了
在这里插入图片描述
这样调整之后,运行结果就没有问题了。
在这里插入图片描述

启用Druid数据源集成Mybatis

既然能集成JdbcTemplate,那么肯定能集成Mybatis啦,我们再来创建一个 “小项目” 玩玩。
第一步:创建数据库
还是使用上面测试JdbcTemplate集成用到的数据库表(如下)
在这里插入图片描述
第二步:创建UserInfo和UserMapper
接着使用Mybatis逆向工程创建UserInfo,UserInfoMapper,UserInfo的代码就不放出来了哈,我这里为了能快速的演示出效果,就没有使用UserMapper.xml了,改用Mybatis的注解方式,也算是复习一下Mybatis的知识啦~

package com.marco.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.marco.domain.UserInfo;

public interface UserInfoMapper {
	@Delete(value="delete from userinfo where u_id = #{value}")
    int deleteByPrimaryKey(Integer uId);
	@Insert("insert into userinfo(u_uname,u_pwd,u_tele,u_realname) values(#{uUname}, #{uPwd}, #{uTele}, #{uRealname})")
    int insert(UserInfo userInfo);
	@Update("update userinfo set u_uname=#{uUname}, u_pwd=#{uPwd}, u_tele=#{uTele}, u_realname=#{uRealname}")
    int updateByPrimaryKey(UserInfo userInfo);
	@Select("select u_id as uId, u_uname as uUname,u_pwd as uPwd,u_tele as uTele, u_realname as uRealname, u_regTime as uRegtime from userinfo where u_id = #{value}")
    UserInfo selectByPrimaryKey(Integer uId);
	@Select("select u_id as uId, u_uname as uUname,u_pwd as uPwd,u_tele as uTele, u_realname as uRealname, u_regTime as uRegtime from userinfo")
    List<UserInfo> queryAllUser();
}

第三步:修改pom.xml
这里需要引入mybatis的启动装置mybatis-spring-boot-starter
在这里插入图片描述
另外为了测试分页,以及查看sql运行的日志,我这里还引进了spring-boot-starter-log4j以及com.github.pagehelper
在这里插入图片描述
第四步:修改application.yml

#注入mybatis的配置文件路径
mybatis:
  config-location: 'classpath:mybatis.cfg.xml'

第五步:创建mybatis.cfg.xml
然后创建mybatis.cfg.xml,设置log4j以及分页插件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
    	<setting name="logImpl" value="LOG4J"/>
    </settings>
    <plugins>
    	<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
</configuration>

第六步:扫描UserInfoMapper
这一步虽然很简单,但是至关重要!如果没有扫描mapper,则会抛出下面的异常
在这里插入图片描述

package com.marco;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(basePackages={"com.marco.mapper"})
public class SpringbootDatasourceApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringbootDatasourceApplication.class, args);
	}
}

不过还有一种解决问题的方式就是在UserInfoMapper上方添加@Mapper注解,不过这种方式显得有些 “鸡肋” ,因为当我们的Mapper类多起来之后,每次都要在类上加这么个注解,这样操作会显得很繁琐,因此,比较推荐第一种方式。

第七步:测试

package com.marco;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.marco.domain.UserInfo;
import com.marco.mapper.UserInfoMapper;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootDatasourceApplicationTests {

	@Autowired
	private UserInfoMapper userInfoMapper;
	
	@Test
	public void contextLoads() {
		Page<Object> page = PageHelper.startPage(1, 5);
		List<UserInfo> userInfos = userInfoMapper.queryAllUser();
		for (UserInfo userInfo : userInfos) {
			System.out.println(page.getTotal());
			System.out.println(userInfo);
		}
		System.out.println(userInfoMapper.selectByPrimaryKey(1));
	}
}

因为我数据库只有一条数据,所以,测试结果没有问题
在这里插入图片描述

但是!这种结合mybatis.cfg.xml使用插件的方式显得特别的累赘和多余,因此我们会针对上面的步骤做一些简化,让整个结构看起来没有那么的 “臃肿”。

优化Druid数据源集成Mybatis的配置

第一步:修改yml
删除config-location: 'classpath:mybatis.cfg.xml',然后添加以下配置
在这里插入图片描述
上面这两条配置分别帮我们完成了log日志的设置以及注入Mapper.xml的配置(如果用上面的方法需要在mybatis.cfg.xml中注入)
第二步:修改pom.xml
接着剔除咱们之前的mybatis.cfg.xml文件,加上pagehelper的 “启动装置”,并删除之前导入pagehelper的引入jar包
在这里插入图片描述
第三步:删除log4j.properties
接着删除咱们之前的log4j.properties,避免和我们上面注入的log4j的配置产生冲突

完成上述三步操作之后,咱们再来测试看看效果如何?
在这里插入图片描述
也没有任何问题!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值