二、Mybatis 常用工具类

  • 源码地址:https://github.com/RononoaZoro/mybatis-book/tree/master 的 mybatis-book ( mybatis-chapter03 )

  • 文章内容出自《Mybatis 3 源码深度解析》第三章
    资源文件

  • create-table.sql

drop table user if exists;
create table user (
  id int generated by default as identity,
  create_time varchar(20) ,
  name varchar(20),
  password varchar(36),
  phone varchar(20),
  nick_name varchar(20),
  primary key (id)
);
  • init-data.sql
insert into user (create_time, name, password, phone, nick_name) values('2010-10-23 10:20:30', 'User1', 'test', '18700001111', 'User1');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-24 10:20:30', 'User2', 'test', '18700001111', 'User2');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-25 10:20:30', 'User3', 'test', '18700001111', 'User3');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User4', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User5', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User6', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User7', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User8', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User9', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User10', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User11', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User12', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User13', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User14', 'test', '18700001111', 'User4');

1、使用 SQL 类生成语句

  • SQL 类用于生成 sql 语句
package com.blog4java.mybatis;

import org.apache.ibatis.jdbc.SQL;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class SQLExample {

    @Test
    public void testSelectSQL() {
        String orgSql = "SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON\n" +
                        "FROM PERSON P, ACCOUNT A\n" +
                        "INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID\n" +
                        "INNER JOIN COMPANY C on D.COMPANY_ID = C.ID\n" +
                        "WHERE (P.ID = A.ID AND P.FIRST_NAME like ?) \n" +
                        "OR (P.LAST_NAME like ?)\n" +
                        "GROUP BY P.ID\n" +
                        "HAVING (P.LAST_NAME like ?) \n" +
                        "OR (P.FIRST_NAME like ?)\n" +
                        "ORDER BY P.ID, P.FULL_NAME";

        String newSql =  new SQL() {{
                    SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
                    SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
                    FROM("PERSON P");
                    FROM("ACCOUNT A");
                    INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
                    INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
                    WHERE("P.ID = A.ID");
                    WHERE("P.FIRST_NAME like ?");
                    OR();
                    WHERE("P.LAST_NAME like ?");
                    GROUP_BY("P.ID");
                    HAVING("P.LAST_NAME like ?");
                    OR();
                    HAVING("P.FIRST_NAME like ?");
                    ORDER_BY("P.ID");
                    ORDER_BY("P.FULL_NAME");
                }}.toString();

        assertEquals(orgSql, newSql);
    }

    @Test
    public void testDynamicSQL() {
        selectPerson(null,null,null);
    }

    public String selectPerson(final String id, final String firstName, final String lastName) {
        return new SQL() {{
            SELECT("P.ID, P.USERNAME, P.PASSWORD");
            SELECT("P.FIRST_NAME, P.LAST_NAME");
            FROM("PERSON P");
            if (id != null) {
                WHERE("P.ID = #{id}");
            }
            if (firstName != null) {
                WHERE("P.FIRST_NAME = #{firstName}");
            }
            if (lastName != null) {
                WHERE("P.LAST_NAME = #{lastName}");
            }
            ORDER_BY("P.LAST_NAME");
        }}.toString();
    }

    @Test
    public  void testInsertSql() {
        String insertSql = new SQL().
            INSERT_INTO("PERSON").
            VALUES("ID, FIRST_NAME", "#{id}, #{firstName}").
            VALUES("LAST_NAME", "#{lastName}").toString();
        System.out.println(insertSql);
    }

    @Test
    public void  testDeleteSql() {
        String deleteSql =  new SQL() {{
            DELETE_FROM("PERSON");
            WHERE("ID = #{id}");
        }}.toString();
        System.out.println(deleteSql);
    }

    @Test
    public void testUpdateSql() {
        String updateSql =  new SQL() {{
            UPDATE("PERSON");
            SET("FIRST_NAME = #{firstName}");
            WHERE("ID = #{id}");
        }}.toString();
        System.out.println(updateSql);
    }


}

2、使用 ScriptRunner 执行脚本

  • ScriptRunner 类用于执行外部资源的 sql 脚本
package com.blog4java.mybatis;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;

public class ScriptRunnerExample {

    @Test
    public void testScriptRunner() {
        try {
            Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:mybatis",
                    "sa", "");
            ScriptRunner scriptRunner = new ScriptRunner(connection);
            scriptRunner.runScript(Resources.getResourceAsReader("create-table.sql"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3、使用 SqlRunner 操作数据库

  • SqlRunner 用于执行 sql 语句
package com.blog4java.mybatis;

import com.alibaba.fastjson.JSON;
import com.blog4java.common.IOUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.SQL;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.apache.ibatis.jdbc.SqlRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

public class SqlRunnerExample {

    Connection connection = null;

    @Before
    public void initTable() throws SQLException, IOException {
        connection = DriverManager.getConnection("jdbc:hsqldb:mem:mybatis",
                "sa", "");
        ScriptRunner scriptRunner = new ScriptRunner(connection);
        scriptRunner.setLogWriter(null);
        scriptRunner.runScript(Resources.getResourceAsReader("create-table.sql"));
        scriptRunner.runScript(Resources.getResourceAsReader("init-data.sql"));
    }

    @Test
    public void testSelectOne() throws SQLException {
        SqlRunner sqlRunner = new SqlRunner(connection);
        String qryUserSql = new SQL() {{
            SELECT("*");
            FROM("user");
            WHERE("id = ?");
        }}.toString();
        Map<String, Object> resultMap = sqlRunner.selectOne(qryUserSql, Integer.valueOf(1));
        System.out.println(JSON.toJSONString(resultMap));
    }

    @Test
    public void testDelete() throws SQLException {
        SqlRunner sqlRunner = new SqlRunner(connection);
        String deleteUserSql = new SQL(){{
            DELETE_FROM("user");
            WHERE("id = ?");
        }}.toString();
        sqlRunner.delete(deleteUserSql, Integer.valueOf(1));
    }

    @Test
    public void testUpdate() throws SQLException {
        SqlRunner sqlRunner = new SqlRunner(connection);
        String updateUserSql = new SQL(){{
            UPDATE("user");
            SET("nick_name = ?");
            WHERE("id = ?");
        }}.toString();
        sqlRunner.update(updateUserSql, "Jane", Integer.valueOf(1));
    }

    @Test
    public void testInsert() throws SQLException {
        SqlRunner sqlRunner = new SqlRunner(connection);
        String insertUserSql = new SQL(){{
            INSERT_INTO("user");
            INTO_COLUMNS("create_time,name,password,phone,nick_name");
            INTO_VALUES("?,?,?,?,?");
        }}.toString();
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        sqlRunner.insert(insertUserSql,createTime,"Jane","test","18700000000","J");
    }

    @After
    public void closeConnection() {
        IOUtils.closeQuietly(connection);
    }


}

4、MetaObject 详解

  • MetaObject 用于通过反射获取和设置对象的属性值
package com.blog4java.mybatis;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;


public class MetaObjectExample {

    @Data
    @AllArgsConstructor
    private static class User {
        List<Order> orders;
        String name;
        Integer age;
    }

    @Data
    @AllArgsConstructor
    private static class Order {
        String orderNo;
        String goodsName;
    }

    @Test
    public void testMetaObject() {
        List<Order> orders = new ArrayList() {
            {
                add(new Order("order20171024010246", "《Mybatis源码深度解析》图书"));
                add(new Order("order20171024010248", "《AngularJS入门与进阶》图书"));
            }
        };
        User user = new User(orders, "archerLuo", 3);
        MetaObject metaObject = SystemMetaObject.forObject(user);
        // 获取第一笔订单的商品名称
        System.out.println(metaObject.getValue("orders[0].goodsName"));
        // 获取第二笔订单的商品名称
        System.out.println(metaObject.getValue("orders[1].goodsName"));
        // 为属性设置值
        metaObject.setValue("orders[1].orderNo","order20181113010139");
        // 判断User对象是否有orderNo属性
        System.out.println("是否有orderNo属性且orderNo属性有对应的Getter方法:" + metaObject.hasGetter("orderNo"));
        // 判断User对象是否有name属性
        System.out.println("是否有name属性且orderNo属性有对应的name方法:" + metaObject.hasGetter("name"));

    }
}

5、MetaClass 详解

  • MetaClass 用于获取类(对象的 Class 对象)的信息
package com.blog4java.mybatis;

import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaClass;
import org.apache.ibatis.reflection.invoker.Invoker;
import org.junit.Test;

import java.lang.reflect.InvocationTargetException;

public class MetaClassExample {

    @Data
    @AllArgsConstructor
    private static class Order {
        String orderNo;
        String goodsName;
    }

    @Test
    public void testMetaClass() {
        MetaClass metaClass = MetaClass.forClass(Order.class, new DefaultReflectorFactory());
        // 获取所有有Getter方法的属性名
        String[] getterNames = metaClass.getGetterNames();
        System.out.println(JSON.toJSONString(getterNames));
        // 是否有默认构造方法
        System.out.println("是否有默认构造方法:" + metaClass.hasDefaultConstructor());
        // 某属性是否有对应的Getter/Setter方法
        System.out.println("orderNo属性是否有对应的Getter方法:" + metaClass.hasGetter("orderNo"));
        System.out.println("orderNo属性是否有对应的Setter方法:" + metaClass.hasSetter("orderNo"));

        System.out.println("orderNo属性类型:" + metaClass.getGetterType("orderNo"));

        // 获取属性Getter方法
        Invoker invoker = metaClass.getGetInvoker("orderNo");
        try {
            // 通过Invoker对象调用Getter方法获取属性值
            Object orderNo = invoker.invoke(new Order("order20171024010248","《Mybatis源码深度解析》图书"), null);
            System.out.println(orderNo);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}

6、ObjectFactory 详解

  • ObjectFactory 用于生成所需的通用对象
package com.blog4java.mybatis;

import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class ObjectFactoryExample {

    @Test
    public void testObjectFactory() {
        ObjectFactory objectFactory = new DefaultObjectFactory();
        List<Integer> list = objectFactory.create(List.class);
        Map<String,String> map = objectFactory.create(Map.class);
        list.addAll(Arrays.asList(1, 2, 3));
        map.put("test", "test");
        System.out.println(list);
        System.out.println(map);
    }
}

7、ProxyFactory 详解

  • ProxyFactory 用于生成对象的动态代理对象
package com.blog4java.mybatis;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.ibatis.executor.loader.ProxyFactory;
import org.apache.ibatis.executor.loader.ResultLoaderMap;
import org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.session.Configuration;
import org.junit.Test;

import java.util.Arrays;

import static org.mockito.Mockito.mock;

public class ProxyFactoryExample {

    @Data
    @AllArgsConstructor
    private static class Order {
        private String orderNo;
        private String goodsName;
    }

    @Test
    public void testProxyFactory() {
        // 创建ProxyFactory对象
        ProxyFactory proxyFactory = new JavassistProxyFactory();
        Order order = new Order("gn20170123","《Mybatis源码深度解析》图书");
        ObjectFactory objectFactory = new DefaultObjectFactory();
        // 调用ProxyFactory对象的createProxy()方法创建代理对象
        Object proxyOrder = proxyFactory.createProxy(order
                ,mock(ResultLoaderMap.class)
                ,mock(Configuration.class)
                ,objectFactory
                ,Arrays.asList(String.class,String.class)
                ,Arrays.asList(order.getOrderNo(),order.getGoodsName())
        );
        System.out.println(proxyOrder.getClass());
        System.out.println(((Order)proxyOrder).getGoodsName());
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值