Spring Boot访问数据库

SpringBoot访问数据库时,我们可以使用以下三种,JdbcTemplate、Spring Boot Data Jpa、mybatis。

JdbcTemplate是Spring自己提供的,但是其操作不方便,甚至有些繁琐,在实际应用中也是很少会使用,所以这里就不过多介绍了,感兴趣的小伙伴可以自行百度了解。

Spring Boot Data Jpa是基于Hibernate框架来实现的,Hibernate是一个全自动的框架,曾经也和mybatis一样流行,不过Hibernate不方便自定义sql,这便使得其无法满足如今的互联网环境,所以也是渐渐没落了,所以这里也是不过多介绍了,感兴趣的小伙伴可以自行百度了解。

mybatis是一个半自动框架,需要开发者自定义sql,这也使得其可以开发出性能很高的应用,所以现在它也已经成为了目前Java持久层最流行的框架,所以我们这个篇章主要介绍Spring Boot中关于mybatis的使用。

Spring Boot整合Mybatis框架

Spring Boot的默认配置中是不包含mybatis框架的,但是mybatis开发社区自己开发了Spring Boot的启动包。
首先,我们在项目中添加mybatis的依赖以及mysql数据库的依赖,如下所示:

		<!--mysql数据库依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--mybatis依赖-->
        <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

这样,我们就可以在项目中使用mysql数据库以及mybatis框架了。

mybatis的配置

mybatis框架的配置文件主要包括两大部分,一个是基础配置文件,还有一个就是映射文件。其中映射文件也可以通过注解的方式配置,但是因为注解的功能以及可读性的限制,所以这里我们不采用注解的方式,而是采用xml方式来处理映射文件。

mybatis操作的核心是SqlSession接口对象,它是由SqlSessionFactory对象来创建的,SqlSessionFactory这个对象的作用也就是为了创建SqlSession接口对象,作用单一,所以在mybatis应用的生命周期中应该只存在一个SqlSessionFactory对象,并且一般都会使用单例模式。

构建SqlSessionFactory对象是需要通过配置类Configuration来完成的,可以在Spring Boot的application.properties文件中配置。下面让我们来看看都可以配置哪些内容。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

mybatis别名的使用

为了避免在mybatis的映射文件中书写POJO类的全限定名称(很长,不方便),mybatis提出了别名的概念,就是在mybatis的世界中,给某个POJO类取一个别名,这样mybatis就可以根据这个别名来找到对应的POJO类了。
首先我们创建一个User类,并且采用@Alias注解设置其别名为“user”,代码如下:

@Data
@Accessors(chain = true)
@Alias("user")
public class User {

    private Long id;

    private String userName;

    private SexEnum sex;

}
自定义typeHandler

注意,性别这里,我们采用了枚举类型,所以需要对这个属性开发我们自己的typeHandler来完成从数据库到POJO类的转换,代码如下:

@MappedJdbcTypes(value = JdbcType.INTEGER)
@MappedTypes(value = SexEnum.class)
public class SexTypeHandler extends BaseTypeHandler<SexEnum> {
    /**
     * 设置非空性别参数
     */
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, SexEnum sexEnum, JdbcType jdbcType) throws SQLException {
        preparedStatement.setInt(i, sexEnum.getSex());
    }

    /**
     * 根据列名读取性别
     */
    @Override
    public SexEnum getNullableResult(ResultSet resultSet, String s) throws SQLException {
        int sex = resultSet.getInt(s);
        return SexEnum.getBySex(sex);
    }

    /**
     * 根据下标读取性别
     */
    @Override
    public SexEnum getNullableResult(ResultSet resultSet, int i) throws SQLException {
        int sex = resultSet.getInt(i);
        return SexEnum.getBySex(sex);
    }

    /**
     * 根据存储过程读取性别
     */
    @Override
    public SexEnum getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return null;
    }
}

在mybatis中,对于typeHandler的要求是需要实现TypeHandler接口,而抽象类BaseTypeHandler也是实现了TypeHandler接口,并且还扩展了其他功能,所以这里我们直接继承抽象类BaseTypeHandler即可。

另外,我们用@MappedJdbcTypes(value = JdbcType.INTEGER)注解设置了性别属性在数据库中的类型,@MappedTypes(value = SexEnum.class)注解设置性别属性在POJO类中的类型。这样,它们就可以互相转换了。

配置映射文件

下面我们创建映射文件UserMapper.xml,内容如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zzm.mapper.UserMapper">

    <select id="getById" parameterType="long" resultType="user">
        select id,user_name as userName,sex from zzm_sp_learn_user_info where id = #{id}
    </select>
</mapper>

namespace中对应的com.zzm.mapper.UserMapper接口如下:

@Repository
public interface UserMapper {
    User getById(long id);
}

有了上面的内容,我们在application.properties文件中添加以下配置:

#mybatis映射文件位置配置
mybatis.mapper-locations=classpath:mapper/*.xml
#mybatis扫描别名的包,和@Alias注解联合使用
mybatis.type-aliases-package=com.zzm.pojo
#mybatis的typehandler扫描包配置
mybatis.type-handlers-package=com.zzm.typehandler

#日志配置
logging.level.root=DEBUG
logging.level.org.springframework=DEBUG
logging.level.org.org.mybatis=DEBUG

将日志级别设置为DEBUG是为了方便调试。

对于mybatis的配置到这里就可以了,mybatis-spring-boot-starter已经提供了其他的默认配置,所以这里我们只需要修改我们需要的配置即可,这便是Spring Boot的魅力,以最少的配置进行开发。
下面我们一起看看怎么在Spring Boot中整合它。

Spring Boot中整合mybatis

Spring Boot装配mybatis接口主要有以下几种方式:

  • MapperFactoryBean 针对于一个接口配置
  • MapperScannerConfigurer 扫描装配
  • @MapperScan 扫描装配,和@Repository注解配合使用(相比前两种,这个更加简便,所以实际应用中推荐用这个)
  • @Mapper

下面让我们依次看一下这几种的使用。

MapperFactoryBean

MapperFactoryBean一次只能向SpringBoot装配一个mybatis接口,所以这里只是简单介绍。用法如下:

@Bean
    public MapperFactoryBean<UserMapper> initUserMapper(){
        MapperFactoryBean<UserMapper> mapperFactoryBean = new MapperFactoryBean<>();
        mapperFactoryBean.setMapperInterface(UserMapper.class);
        mapperFactoryBean.setSqlSessionFactory(sqlSessionFactory);

        return mapperFactoryBean;
    }

MapperScannerConfigurer

实际中,我们的mybatis接口不可能只有一个,而这个类可以配置mybatis接口的扫描规则,实现批量装配的效果。用法如下:

@Bean
    public MapperScannerConfigurer mapperScannerConfigurerInit(){
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        mapperScannerConfigurer.setBasePackage("com.zzm.*");
        mapperScannerConfigurer.setAnnotationClass(Repository.class);

        return mapperScannerConfigurer;
    }

如代码所示,我们配置了mybatis接口的装配规则如下:

  • 扫描的包路径为“com.zzm.*”;
  • 只有被@Repository注解修饰的接口才会被装配;

@MapperScan 扫描装配

@MapperScan 它是MapperScannerConfigurer 的注解版本,因为SpringBoot推荐使用注解开发,所以这里也推荐大家实际应用中使用这个。
用法如下:

@SpringBootApplication
@Slf4j
@MapperScan(basePackages = {"com.zzm.*"}, annotationClass = Repository.class)
public class Application {
	......
}

这里配置的扫描规则和MapperScannerConfigurer配置的是一样的。

@Mapper

这个注解和@Repository注解功能都是一样的,都是将mybaits的接口交由Spring管理,但是相比于@Repository注解,@Mapper注解更加方便。

使用时,仅需要用@Mapper注解修饰需要装配的mubaits接口就可以了,不再需要上述的配置,如下所示:

@Mapper
public interface UserMapper {
    User getById(long id);
}

@SpringBootApplication
@Slf4j
public class Application {
	.......
}

关于@Repository和@Mapper的区别,可参考如下:

@Repository@Mapper
Spring提供的注解mybatis提供的注解
需要配置扫描地址不需要配置扫描地址,通过xml里面的namespace里面的接口地址,生成了Bean后注入到Service层中

接下来我们创建测试controller和service(这两个很简单,这里就不过多介绍了),访问测试地址,可以看到效果如下:
在这里插入图片描述
数据库中的数据如下:
在这里插入图片描述
细心的小伙伴可能已经发现,用户信息中的性别属性值,在我们调用接口查询时自动转换成了枚举类型,而这个工作就是我们前面配置的自定义类型转换器SexTypeHandler 实现的。
而此时的mybatis映射文件中也需要配置我们的自定义类型转换器,如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zzm.mapper.UserMapper">

    <resultMap id="baseMap" type="user">
        <result column="id" property="id" javaType="long" jdbcType="BIGINT"/>
        <result column="user_name" property="userName" javaType="String" jdbcType="VARCHAR"/>
        <result column="sex" property="sex" javaType="sexEnum" jdbcType="SMALLINT" typeHandler="sexTypeHandler"/>
    </resultMap>

    <select id="getById" parameterType="long" resultMap="baseMap">
        select id,user_name,sex from zzm_sp_learn_user_info where id = #{id}
    </select>
</mapper>

mybatis插件

这里我们介绍一下mybatis的插件机制。比如我们如果想在保存或者更新用户信息时,想同时更新对应的创建时间、更新时间、创建人、更新人等信息,那需要怎么做呢?

当然,我们可以在代码中或者sql中完成这个工作,但是如果有很多不同类的数据也需要保存这些信息呢?比如学校信息、课程信息、学生信息…等,如果每个类都要在代码中或者sql中完成这个工作,那无疑会造成大量的重复代码。
所以针对于这个场景,我们就可以采用mybatis的插件机制来完成了。
首先我们在用户表中添加更新人和更新时间两个字段,它俩会在用户信息新增或者保存时同步更新。
在这里插入图片描述

定义一个mybatis插件

接下来我们定义一个mybatis插件:

@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class,Object.class})
})
@Slf4j
public class MyPlugin implements Interceptor {

    Properties properties;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        log.warn("插件拦截方法......");
        for(Object obj : invocation.getArgs()){
            if(obj instanceof User){
                User user = (User) obj;
                user.setUpdatedBy(123456L);
                user.setUpdateTime(new Date());
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}

这里我们设置了拦截mybatis的update方法(即数据的保存和更新都会被拦截到),并且将方法的参数也传了进来。
在方法intercept中,我们拦截了user对象,并且将其更新时间和更新人分别赋值,这样,mybatis在保存数据到数据库时,也会将更新时间和更新人同步保存。

注册插件到Spring

定义好了插件,还需要将其注册到Spring容器中,注册代码如下:

@SpringBootApplication
@Slf4j
public class Application {

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        log.warn("启动成功......");
    }

    @PostConstruct
    public void initMybatis(){
        Interceptor plugin = new MyPlugin();
        Properties properties = new Properties();
        properties.setProperty("k1","v1");
        properties.setProperty("k2","v2");
        properties.setProperty("k3","v3");

        plugin.setProperties(properties);

        sqlSessionFactory.getConfiguration().addInterceptor(plugin);
    }

可以看到,我们在注册插件时,还传递了k1,k2,k3三个属性值,这样,我们就可以在插件中使用这三个值了

最后,启动应用,访问测试接口,测试效果如下:
在这里插入图片描述

在这里插入图片描述
好了,今天就先到这里了,眼过千遍不如手过一遍,赶紧去自己尝试一下吧。。。。拜拜

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值