mybatis的工具类
1.SQL:使用JDBC拼接SQL的开发中,空格操作和逗号是噩梦.使用sql类生成sql语句
源码实现:SQL类继承自AbstractSQL。AbstractSQL:SQL工具类所有的功能都由AbstractSQL类实现。这个类的作用就是拼接sql语句
public class SQL extends AbstractSQL<SQL> { @Override public SQL getSelf() { return this; } }
SQLStatement内部类: SqlStatementType判断sql的类型
sqlCause:进行sql语句拼接
AbstractSQL重写sql.toString方法,用来拼接sql
优点:避免忘了空格或者逗号
可以方便的在java代码中拼接动态sql语句
2.ScriptRunner执行脚本
a.作用:读取文件中的sql并执行
b.代码演示:
@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(); } } public void runScript(Reader reader) { // 设置事务是否自动提交 setAutoCommit(); try { // 是否一次性批量执行脚本文件中的所有SQL语句 if (sendFullScript) { // 调用executeFullScript()方法一次性执行脚本文件中的所有SQL语句 executeFullScript(reader); } else { // 调用executeLineByLine()方法逐条执行脚本中的SQL语句 executeLineByLine(reader); } } finally { rollbackConnection(); } }
3.使用SQLRunner操作数据库
MyBatis中提供了一个非常实用的、用于操作数据库的SqlRunner工具类,该类对JDBC做了很好的封装,结合SQL工具类,能够很方便地通过Java代码执行SQL语句并检索SQL执行结果。
SqlRunner类提供了几个操作数据库的方法,分别说明如下。
● SqlRunner#closeConnection():用于关闭Connection对象。 ● SqlRunner#selectOne(String sql, Object.. args):执行SELECT语句,SQL语句中可以使用占位符,如果SQL中包含占位符,则可变参数用于为参数占位符赋值,该方法只返回一条记录。若查询结果行数不等于一,则会抛出SQL Exception异常。 ● SqlRunnen#selectAll(String sq|, Object.. args): 该方法和selectOne()方法的作用相同,只不过该方法可以返回多条记录,方法返回值是一个List对象, List中包含 多个Map对象,每个Map对象对应数据库中的一行记录。 ● SqlRunner#insert(String sql, Object.. args):执行一条INSERT语句,插入一条记录。 ● SqlRunnen#update(String sql, Object.. args):更新若干条记录。 ● SqlRunner#delete(String sql, Object.. args):删除若干条记录。 ● SqlRunner#run(String sq):执行任意一条SQL语句, 最好为DDL语句。
操作案例:
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工具类:优雅的获取和设置对象的属性值
5.MetaClass工具类:作用:获取类相关信息
代码相关案例:
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
7.ProxyFactory
ProxyFactory是MyBatis中的代理工厂,主要用于创建动态代理对象,ProxyFactory接口有两个不同的实现,分别为CglibProxyFactory和JavassistProxyFactory。从实现类的名称可以看出,MyBatis支持两种动态代理策略,分别为Cglib和Javassist动态代理。ProxyFactory主要用于实现MyBatis的懒加载功能。当开启懒加载后,MyBatis创建Mapper映射结果对象后,会通过ProxyFactory创建映射结果对象的代理对象。当我们调用代理对象的Getter方法获取数据时,会执行CglibProxyFactory或JavassistProxyFactory中定义的拦截逻辑,然后执行一-次额外的查询。