Mybatis应用分析

从jdbc开始

首先,我们来看一段原生jdbc的代码

public class JdbcDemo {    static {        try {            Class.forName("com.mysql.cj.jdbc.Driver");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }    }    public static void main(String[] args) throws Exception {        Connection connection = null;        PreparedStatement preparedStatement = null;        ResultSet resultSet = null;        try {            connection = getConnection();            preparedStatement = connection.prepareStatement("select * from user where id = ?");            preparedStatement.setLong(1, 1L);            resultSet = preparedStatement.executeQuery();            User user = null;            while (resultSet.next()) {                long id = resultSet.getLong("id");                String userName = resultSet.getString("user_name");                String name = resultSet.getString("name");                int age = resultSet.getInt("age");                user = new User(id, userName, name, age);            }            System.out.println(user);        } catch (Exception e) {            e.printStackTrace();        } finally {            if (resultSet != null) {                resultSet.close();            }            if (preparedStatement != null) {                preparedStatement.close();            }            if (connection != null) {                connection.close();            }        }    }    public static Connection getConnection() throws SQLException {        return DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true", "root", "root");    }}

我们可以看到,从获取获取Connection到关闭Connection释放资源,都需要用户管理,十分繁琐,而且对象映射,sql都采用硬编码,管理十分不方便

接下来,我们来看一下spring对jdbc的封装

                    
public class SpringJdbcDemo {    public static void main(String[] args) {        ClassPathXmlApplicationContext context =                new ClassPathXmlApplicationContext("classpath:spring-jdbc.xml");        JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);        List query = jdbcTemplate.query("select * from user where id = ?", new User(), 1L);        System.out.println(query);    }}

spring对jdbc进行了封装,提供了数据源的管理,并提供了一个模板方法对数据库进行操作,但是,此时sql还是和代码耦合在一直,并且,我们无法直接象操作java bean一样对数据库进行操作。

mybatis的基本使用

mybatis是一个半自动的orm框架,它完美的解决了我们遇到的各种问题,他提供了数据源管理,sql管理,java bean和sql的相互映射,事务,缓存等各个方面的功能。接下来,我们来从一个例子了解mybatis的使用以及相关的配置

  • dao
public interface UserDao {    User get(User user);}
  • entity
@Data@ToString@NoArgsConstructor@AllArgsConstructorpublic class User {    private Long id;    private String userName;    private String name;    private Integer age;    public User(Long id) {        this.id = id;    }}
  • UserDao.xml
<?xml version="1.0" encoding="UTF-8" ?>    
  • mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>                                                                                                                                                                                                                                                                                                                         
  • demo
public class MybatisDemo {    public static void main(String[] args) throws IOException {        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);        SqlSession sqlSession = sqlSessionFactory.openSession();        UserDao userDao = sqlSession.getMapper(UserDao.class);        User user = new User(1L);        user = userDao.get(user);        System.out.println(user);    }}

通过这个简单的实例代码,我们可以看到,在使用spring的时候,我们只需要配置先用的数据源,mapper资源类(其他配置都有其默认值),并为mapper文件创建一个对应的接口,我们就可以直接从SqlSession中获取这个接口对象,然后像操作java bean样去操作数据库

mybatis的配置

setting

  • cacheEnabled
  • 是否开启二级缓存,这个是一个全局的开关,当设置为false时,所有的二级缓存都会被关闭,当设置为true,并且在mapper文件中配置了标签时,当前mapper才会使用二级缓存
  • lazyLoadingEnabled
  • 是否延迟加载,当设置为true时,针对,标签都会使用延迟加载
  • aggressiveLazyLoading
  • 延迟加载的加载时机,默认是只会在使用相应的延迟加载属性时,才会再次查询数据库,加载相应的数据,对于访问其他属性,则不会加载
  • defaultExecutorType
  • 执行器类型,在mybatis中,执行器分为三种类型,SIMPLE,REUSE,BATCCH,reuse对于相同的sql'可以重复使用statement,batch不知可以重复使用statement,还可以进行批量发送sql

typealias

对于返回的java bean,一般,我们需要指定类的全名,针对这种情况,我们可以给这个类配置一个别名,然后在设置返回类型的时候就可以直接使用这个别名

typeHandler

在mybatis中,是如何做到将java bean 映射成sql,有时如何将sql映射成java bean 的呢,其实,这个里面用的就是typeHandler,之所有我们基本没有配置过typeHandler,是因为在mybatis中内置的许多默认的typeHandler,它可以将我们常用的数据类型直接进行映射

public class MyTypeHandler extends BaseTypeHandler {    @Override    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {        String json = JSON.toJSONString(parameter);        ps.setString(i, json);    }    @Override    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {        String json = rs.getString(columnName);        if (json != null) {            return JSON.parseObject(json);        }        return null;    }    @Override    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {        String json = rs.getString(columnIndex);        if (json != null) {            return JSON.parseObject(json);        }        return null;    }    @Override    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {        String json = cs.getString(columnIndex);        if (json != null) {            return JSON.parseObject(json);        }        return null;    }}

plugins

在mybatis中,提供了一种插件机制,他能够让我们在不更改源码的情况下,扩展mybatis的功能,更改mybatis的核心功能,通过mybatis的插件,我们可以实现像打印日志,分页等功能

@Intercepts({        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class ExamplePlugin implements Interceptor {    private Properties properties = new Properties();    public Object intercept(Invocation invocation) throws Throwable {        MappedStatement ms = (MappedStatement) invocation.getArgs()[0];        Object args = invocation.getArgs()[0];        BoundSql boundSql = ms.getBoundSql(args);        String sql = boundSql.getSql();        System.out.println(sql);        Object returnObject = invocation.proceed();        return returnObject;    }    public void setProperties(Properties properties) {        this.properties = properties;    }}
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章