Mybatis基础姿势深入大解析

1. JDBC连接数据库

基础回顾:在咱们的JAVA里面怎么连接数据库?

首先引入MySQL连接驱动maven依赖:

<!-- mysql driver -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
@SpringBootTest
class MyJDBCTest {
    
    
	 /**
     * @Description: jdbc test
     * @Author create by mamba
     * @Date 2020/7/7 11:18
     * @param {}
     */
    @Test
    void myJDBC(){
    
    
        Connection connection = null;
        Statement statement = null;
        Saying saying = new Saying();
        try{
    
    
            // register JDBC Driver
            Class.forName("com.mysql.jdbc.Driver");
            // open connection
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/commentsystem?serverTimezone=UTC", "root", "607918");
            statement = connection.createStatement();
            String sql = "select * from saying where 1=1";
            ResultSet resultSet = statement.executeQuery(sql);
            while (resultSet.next()){
    
    
                Integer sayingId = resultSet.getInt("saying_id");
                String author = resultSet.getString("author");
                String sayingContent = resultSet.getString("sayingContent");
                String likes = resultSet.getString("likes");
                Date createTime = resultSet.getDate("createTime");
                saying.setSaying_id(sayingId);
                saying.setAuthor(author);
                saying.setSayingContent(sayingContent);
                saying.setLikes(likes);
                saying.setCreateTime(createTime);
                System.out.println(saying);
            }
            // close sequence 相反跟打开的顺序
            resultSet.close();
            statement.close();
            connection.close();
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }
}
// print result
Saying{
    
    saying_id=1, author='huanghedidi', sayingAvatar='null', sayingContent='我喜欢,父亲的散文诗', likes='1,2,3,4,8', createTime=2019-05-06}
Saying{
    
    saying_id=2, author='huanghedidi', sayingAvatar='null', sayingContent='second_test', likes='11', createTime=2019-05-03}

思考:当项目复杂庞大时候 直接使用原生的API会带那些问题?
1. 大量的重复性代码,SQL和业务代码耦合度极高, 维护难度很大,不利于项目迭代
2. 加大了出错概率 结果集需要手动处理 加大了开发难度
3. 需要手动管理JDBC资源

2. Spring JDBC

在spring里面对JDBC的封装 是怎么连接数据库?

我们先大体看一下spring的板块图,可见在spring的Data Access/Integration模块包括了对JDBC ORM等进行封装,如果要是用spring封装好的JDBCTemplate,需要引入对应的maven依赖:

 <!-- 引入spring JDBC-->
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jdbc</artifactId>
     <version>${spring.version}</version>
 </dependency>

spring板块模型

思考:引入spring的JDBC之后 我们应该怎么样的访问数据库呢?
其实spring对于Redis MongoDB RabbitMQ等 都提供了对应的template进行封装 简化开发人员操作
1. JDBCTemplate 对于数据库的连接管理 资源管理

2.1 spring JDBC对于结果集的处理

1.实现RowMapper接口,mapRow()方法

public class SayingRowMapper implements RowMapper {
    
    
    @Override
    public Object mapRow(ResultSet resultSet, int i) throws SQLException {
    
    
        Saying saying = new Saying();
        saying.setSaying_id(resultSet.getInt("saying_id"));
        saying.setAuthor(resultSet.getString("author"));
        saying.setSayingAvatar(resultSet.getString("sayingAvatar"));
        saying.setSayingContent(resultSet.getString("sayingContent"));
        saying.setLikes(resultSet.getString("likes"));
        saying.setCreateTime(resultSet.getDate("createTime"));
        // 因为返回类型是Object 所以即使有多组结果的时候自动进行封装成list 或者 map
        return saying;
    }
}

2.转换结果集返回Object

@Autowired
private JdbcTemplate jdbcTemplate;

private List<Saying> sayings;

@Test
void MyRowMapperTest(){
    
    
    sayings = jdbcTemplate.query("select * from saying where 1=1", new SayingRowMapper());
    sayings.forEach(System.out::println);
}

思考: 这样写好像并没有简单多少啊?还是要手动进行类型转换 对象赋值
1. 需要做数据库字段名称和JAVA对象的字段的名称转换(下划线到驼峰命名)
2. 数据库字段类型转换成JAVA的引用类型或基本类型(tinyInt, int, bigint… varchar, char, text, datetime…)
3. 有没有一个自动的映射方法,解决以上的问题?

public class BaseRowMapper<T> implements RowMapper<T> {
    
    

    private Class<?> targetClazz;
    private HashMap<String, Field> fieldMap;

    public BaseRowMapper(Class<?> targetClazz) {
    
    
        this.targetClazz = targetClazz;
        fieldMap = new HashMap<>();
        Field[] fields = targetClazz.getDeclaredFields();
        for (Field field : fields) {
    
    
            fieldMap.put(field.getName(), field);
        }
    }

    @Override
    public T mapRow(ResultSet rs, int arg1) throws SQLException {
    
    
        T obj = null;

        try {
    
    
            obj = (T) targetClazz.newInstance();

            final ResultSetMetaData metaData = rs.getMetaData();
            int columnLength = metaData.getColumnCount();
            String columnName = null;

            for (int i = 1; i <= columnLength; i++) {
    
    
                columnName = metaData.getColumnName(i);
                Class fieldClazz = fieldMap.get(camel(columnName)).getType();
                Field field = fieldMap.get(camel(columnName));
                field.setAccessible(true);

                // fieldClazz == Character.class || fieldClazz == char.class
                if (fieldClazz == int.class || fieldClazz == Integer.class) {
    
     // int
                    field.set(obj, rs.getInt(columnName));
                } else if (fieldClazz == boolean.class || fieldClazz == Boolean.class) {
    
     // boolean
                    field.set(obj, rs.getBoolean(columnName));
                } else if (fieldClazz == String.class) {
    
     // string
                    field.set(obj, rs.getString(columnName));
                } else if (fieldClazz == float.class) {
    
     // float
                    field.set(obj, rs.getFloat(columnName));
                } else if (fieldClazz == double.class || fieldClazz == Double.class) {
    
     // double
                    field.set(obj, rs.getDouble(columnName));
                } else if (fieldClazz == BigDecimal.class) {
    
     // bigdecimal
                    field.set(obj, rs.getBigDecimal(columnName));
                } else if (fieldClazz == short.class || fieldClazz == Short.class) {
    
     // short
                    field.set(obj, rs.getShort(columnName));
                } else if (fieldClazz == Date.class) {
    
     // date
                    field.set(obj, rs.getDate(columnName));
                } else if (fieldClazz == Timestamp.class) {
    
     // timestamp
                    field.set(obj, rs.getTimestamp(columnName));
                } else if (fieldClazz == Long.class || fieldClazz == long.class) {
    
     // long
                    field.set(obj, rs.getLong(columnName));
                }

                field.setAccessible(false);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

        return obj;
    }

    /**
     * 下划线转驼峰
     * @param str
     * @return
     */
    public static String camel(String str) {
    
    
        Pattern pattern = Pattern.compile("_(\\w)");
        Matcher matcher = pattern.matcher(str);
        StringBuffer sb = new StringBuffer(str);
        if(matcher.find()) {
    
    
            sb = new StringBuffer();
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
            matcher.appendTail(sb);
        }else {
    
    
            return sb.toString();
        }
        return camel(sb.toString());
    }
}

有了这个baseMapper之后 我们处理起来就更加方便了

扫描二维码关注公众号,回复: 11948558 查看本文章
@Test
void MyRowMapperTest(){
    
    
    sayings = jdbcTemplate.query("select * from saying where 1=1", new BaseMapper(Saying.class));
    sayings.forEach(System.out::println);
}

思考:这样还是有一些问题没有解决啊
1. SQL语句硬编码,跟业务代码混在一起
2. 参数只能按顺序传入,插入时候实体类和数据库字段顺序一致
3. 没有实现实体类到数据库插入对应记录的映射
4. 没有实现缓存等功能

3. 什么是ORM框架

为什么叫ORM? ORM框架解决了那些问题?
O: Object对象 R: relation关系型数据库 M: mapper 映射
Java和数据库记录的相互转化
ORM框架图
之前Hibernate也是一个比较优秀的ORM框架,使用hibernateTemplate会自动生成对应crud的语句;

Hibernate存在的缺点:
1. 不能指定部分字段,很不灵活
2. 无法自定义SQL,优化困难
3. 不支持动态SQL

4. Mybatis基本特性

基本特性:
1. 使用连接池对连接进行管理
2. SQL和业务代码分离解耦,集中进行管理
3. 支持参数映射和动态SQL
4. 结果集映射
5. 缓存管理
6. 重复SQL的提取
7. 插件机制,例如分页插件等

应该如何选择ORM框架?

  1. 业务简单 推荐Hibernate
  2. 业务复杂 需要灵活SQL 推荐mybatis
  3. 对性能要求高 推荐直接使用原生的JDBC
  4. Spring JDBC 和ORM混用
  5. 混用ORM基本没见过。。。推荐手写ORM!

猜你喜欢

转载自blog.csdn.net/blackxc/article/details/107174439