mybatis 原理和使用
参考:https://mybatis.org/mybatis-3/zh/getting-started.html
一、JDBC
JDBC 是 Java 和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行 SQL 语句。它由一组用 Java 语言编写的类和接口组成。各种不同类型的数据库都有相应的实现,下面是针对 Mysql 数据库实现的。
public static void main(String[] args) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection("jdbc:mysql://10.10.130.161:3306/my", "root", "123456"); connection.setAutoCommit(false); PreparedStatement preparedStatement = connection .prepareStatement("insert into t_dep (name, age) values (?, ?)"); preparedStatement.setString(1, "xiali1"); preparedStatement.setInt(2, 18); try { preparedStatement.executeUpdate(); connection.commit(); } catch (Exception e){ connection.rollback(); e.printStackTrace(); } finally { if(preparedStatement != null){ preparedStatement.close(); } if(connection != null){ connection.close(); } } }
二、Mybatis 简介
Mybatis 是一个优秀的持久层框架。他是一种对 JDBC 的封装。
每个基于 Mybatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
public static void main(String[] args) throws IOException { // 从配置文件构建 SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 从 SqlSessionFactory 中获取 SqlSession try (SqlSession session = sqlSessionFactory.openSession()) { Dept dept1 = (Dept)session.selectOne("com.pea.mybatis.asconfig.DeptMapper.selectDept",1); System.out.println("dept1 = " + dept1.toString()); DeptMapper mapper = session.getMapper(DeptMapper.class); Dept dept2 = mapper.selectDept(2); System.out.println("dept2 = " + dept2.toString()); } }
三、Mybatis 配置
1. 类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写的名字。它仅用于 XML 配置,意在降低冗余的全限定类名书写。
2. 类型处理器(typeHandlers)
Mybatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时,都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。
可以重写已有的类型处理器或者创建新的类型处理器来处理不支持的或非标准的类型。具体做法为:实现 org,apache,ibatis.type.TypeHandler 接口,或继承 org.apache.ibatis.type.BaseTypeHandler。
3. 对象工厂(objectFactory)
每次 Mybatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。默认的对象工厂做的仅仅是实例化目标类,要么通过无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。如果想要覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现。比如: public class ExampleObjectFactory extends DefaultObjectFactory{...}
4. 插件(plugins)
Mybatis 允许在映射语句执行过程中的某一点进行拦截调用。默认情况下,Mybatis 允许使用插件来拦截的方法调用包括:
- Executor(update,query,flushStatements,commit,rollback,getTransaction,close,isClosed)
- ParameterHandler(getParameterObject,setParameters)
- ResultSetHandler(handleResultSets,handleOutputParameters)
- StatementHandler(prepare,parameterize,batch,update,query)
通过 Mybatis 提供的强大机制,使用插件时,只需要实现 Interceptor 接口,并指定想要拦截的方法签名即可。
@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})) public class SelectInterceptor implements Interceptor { private Properties properties = new Properties(); @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println(" plugin plugin plugin plugin plugin "); final Object[] args = invocation.getArgs(); RowBounds rowBounds = (RowBounds) args[2]; MappedStatement mappedStatement = (MappedStatement) args[0]; Object o = invocation.proceed(); return o; } @Override public Object plugin(Object o) { return Plugin.wrap(o, this); } @Override public void setProperties(Properties properties) { this.properties = properties; } }
除了使用插件来修改 Mybatis 核心行为外,还可以通过完全覆盖配置类来达到目的。只需继承配置类后覆盖其中的某个方法,再把它传递到 SqlSessionFactoryBuilder.build(myConfig) 方法即可。但是,需要谨慎。
四、动态 SQL
<set> 可以忽略最后一个更新字段后面的逗号
<where> 可以忽略第一个前面的 and
<trim> 可以指定忽略
<foreach> 可以用 list、array、myMap.values
五、#{} 和 ${}
#{} 只可以用在 where 后面,才用预编译的方式,能有效防止sql 注入
${} 可以用在任何地方,不能防止 sql 注入,但是如果是表名需要动态获取的,可以用这种方式
六、 级联查询一对多、多对一、多对对
1. 一对多
一对多的实现有两种方式
一种是 <collection ... ofType=... column=... ><id ...><result ...></collection> 关联查询方式
一种是两个独立的 sql 语句合并在一起,<collection .. select="" ... ></collection> 子查询方式,虽然效率不如第一种,但是可以设置延迟加载
2. 多对一
在对象中加上 一方 的对象 <association>
3. 多对多
有中间表的 两个查询