Demo: SpringBoot+Mybatis

前言

最近因工作原因,需要研究下spring的事务部分和mybatis的多数据源的源码实现,这样才能更容易的在代码层面通过扩展/重写等方式去定制自己的实现。

以前虽然用过几次mybatis,但是却一直没抽出时间认真翻看下源码,趁这次机会,花点时间研究下,顺便做个笔记。

关于看源码,我向来是觉得只有一步步去debug整个流程,查看每一步的数据流向和数据状态,才会有个更清晰的深知。如果只是看的话,有些源码中各种继承、适配、代理、装饰等,会分不清当前使用的到底是哪个类。

于是乎,所谓工欲善其事,必先利其器。先搭建个极简单的mybatis的工程环境,用来调试源码。

这个工程用了spring boot+mybatis。mybatis采用java config的形式(是真心不喜欢xml配置,所以源码研究上也会避开xml的加载)

后面博文关于分析描述就会针对这个工程的配置来说了。

另外,代码中关于spring事务的注解先注释了。

说了这么多,是希望缓解自己又写了篇这么没技术含量的博客的尴尬,哎,最近这段时间写的博客确实有些凑数了。

工程代码

数据库脚本:

CREATE DATABASE `testdb` /*!40100 DEFAULT CHARACTER SET utf8 */

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

工程结构

06179DA4-32F0-46E5-F05E-0B58522AFC93.png

按工程结构,列一下文件代码:

User.java

public class User {
    int id;
    int age;
    String username;

    public User() {
    }

    public User(int id, int age, String username) {
        this.id = id;
        this.age = age;
        this.username = username;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", age=" + age +
                ", username='" + username + '\'' +
                '}';
    }
}

MybatisConfig.java

@Configuration
@MapperScan(basePackageClasses = {UserDao.class})
//@EnableTransactionManagement //启用spring事务
public class MybatisConfig {

    @Autowired
    private Environment environment;

    // 数据源配置
    @Bean
    public DataSource dataSource() {
        // mybatis自带的一个简易数据库连接池,只是为了debug代码,这个就不关心了
        PooledDataSource pooledDataSource = new PooledDataSource();
        pooledDataSource.setDriver(environment.getProperty("mysql.driver"));
        pooledDataSource.setUsername(environment.getProperty("mysql.username"));
        pooledDataSource.setPassword(environment.getProperty("mysql.passwd"));
        pooledDataSource.setUrl(environment.getProperty("mysql.url"));
        return pooledDataSource;
    }

    // spring事务管理的基础bean,事务部分会用到
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("classpath:/mapper/*.xml"));
        return sqlSessionFactoryBean;
    }
}

UserController.java

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    IUserService userService;

    @GetMapping("/save")
    public String saveUser() {
        User user = new User(10, 100, "test user");
        try {
            return userService.saveUser(user) ? "save success" : "save fail";
        } catch (Exception ignore) {
            ignore.printStackTrace();// 不打印日志了,堆栈信息直接打到控制台看
            return "save error: " + ignore.getMessage();
        }

    }

    @GetMapping("/list")
    public String getUsers() throws Exception {
        return userService.getUsers().toString();
    }

    @GetMapping("/delete")
    public String deleteUser() throws Exception {
        return userService.deleteUser() ? "delete success" : "delete fail";
    }
}

UserDao.java

@Repository
public interface UserDao {

    boolean saveUser(User user);

    List<User> getUsers();

    boolean deleteUser();

}

UserServiceImpl.java

@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    UserDao userDao;

    //@Transactional //指定这个方法的事务属性
    @Override
    public boolean saveUser(User user) throws Exception {
        boolean success = userDao.saveUser(user);
        // spring事务能力测试的时候,使用下面这段代码
        /*if (true) {
            throw new RuntimeException();
        }*/
        return success;
    }

    @Override
    public List<User> getUsers() throws Exception {
        return userDao.getUsers();
    }

    @Override
    public boolean deleteUser() throws Exception {
        return userDao.deleteUser();
    }
}

IUserService.java

public interface IUserService {

    boolean saveUser(User user) throws Exception;

    List<User> getUsers() throws Exception;

    boolean deleteUser() throws Exception;

}

WebApplication.java

@SpringBootApplication
public class WebApplication {

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

UserMapper.xml

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

    <sql id="user_column">
        id,age,username
    </sql>

    <select id="getUsers" resultType="com.xuxd.demo.beans.User">
        select * from user
    </select>

    <!--  增加用户 -->
    <insert id="saveUser" parameterType="com.xuxd.demo.beans.User">
        insert into user
        (<include refid="user_column"/>)
        values
        (#{id},#{age},#{username})
    </insert>

    <delete id="deleteUser">
        DELETE from USER where id = 10
    </delete>

</mapper>

application.properties

#data source config
mysql.driver=com.mysql.jdbc.Driver
mysql.username=root
mysql.passwd=123456
mysql.url=jdbc:mysql://localhost:3306/testdb?useSSL=false

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xuxd</groupId>
    <artifactId>spring-mybatis.demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.43</version>
        </dependency>
    </dependencies>
</project>

后续就用这个工程debug源码了。

收藏 (0)
评论列表
正在载入评论列表...
我是有底线的
为您推荐
    暂时没有数据