MyBatis 是 iBatis 继任者。不知道为啥 iBatis 没戏了MyBatis 是一种半自动的 ORM 机制。因为简单现在也越来越多 JEE 程序所使用。
文档http://www.mybatis.org/mybatis-3/index.html JavaDochttp://www.mybatis.org/mybatis-3/apidocs/reference/packages.html
这里记录一下我的学习过程。
数据源怎么连接
大家都知道配置文件的方式这里就不赘述了。我们看看不用配置方式写 Java 代码是怎么写的。
MyBatis 把数据源 DataSource 分为三种
- UNPOOLED 不使用连接池的数据源
- POOLED 使用连接池的数据源
- JNDI 使用 JNDI 实现的数据源
使用 UnpooledDataSource 的 getConnection(), 每调用一次就会产生一个新的 Connection 实例对象。MyBatis 创建了 DataSource 实例后会将其放到 Configuration 对象内的 Environment 对象中供以后使用。如果有提供 Connection怎么给 MyBatis 使用答案是…… SqlSession openSession(Connection connection)。
另外源码中比较有意思的地方元数据(metadata) 本包对mybatis的其它包没有任何依赖mybatis的其它包也不依赖于本包即本包可以作为单独的组件或者工具类提出来。包含了3个元数据实体类和一个工厂类Table 是对表的简单封装包括 name,columns,primaryKey,catalogschemaColumn 是对列的简单封装包括 name 和 typeDatabase是对数据库的简单封装包括 catalogschematablesDatabaseFactory 用来创建 Database 对象。缓存类也是org.apache.ibatis.cache。
业务逻辑什么时候调用 MyBastis
如同 JDBC 不需要每次创建 Connection 一样为达到数据库连接复用的效果MyBastis 的数据服务也不需要每次创建。按照官方文档的介绍下面这些都可以在程序初始化阶段生成作为 static 成员公外界访问就好。
class AppStart { public static SqlSessionFactory sqlSessionFactory; private static Reader reader; static { try { Reader reader = Resources.getResourceAsReader("mybatic-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); // 由于使用了注解所以在主配置文件没有mapper需要在代码里显示注册该mapper接口 sqlSessionFactory.getConfiguration().addMapper(IUserDAO.class); } catch (IOException e) { e.printStackTrace(); } } …… }
SqlSession 则是可以反复创建按照你的业务逻辑就好了。注意要记得每次使用 session 完毕都要将其关闭session.close()。如下例子我们使用了 Java 7 的 autoclose 机制无须手动将其关闭。
LOGGER.info("插入一条新记录" + entry.getName()); try (SqlSession session = App.sqlSessionFactory.openSession()) { if (!App.configuration.hasMapper(mapperClz)) { App.configuration.addMapper(mapperClz); } Mapper dao = session.getMapper(mapperClz); effectedRows = dao.create(entry); System.out.println(":::" + entry.getId()); // 自增的 id 会自动保存到 bean 之中 session.commit(); // 默认没有自动提交 } catch (Throwable e) { e.printStackTrace(); throw new DaoException(e.getMessage()); }
SQL 映射
映射文件写好了还要写接口。接口相当于 DAO。
我比较喜欢映射文件的地方就是只需要写接口不需要写实现话说实现存在不存在呢在啊 SQL 逻辑不就变相是一种“实现”吗
除了 XML 映射文件外还有两种方法构建映射关系。这两种方法又因为有互补性所以你把它们当作一种方法也未尝不可。它们分别是直接在映射器接口中写 SQL 语句通过 Annotation 注解一种是利用 SqlBuilder 来创建 SQL 再由映射器接口来调用。所谓互补性是因为我们无法在 Java 注解中写出 if... else于是在 SQL Builder 里面直接写 Java if...else 就可以啦
通过<sql>标签实现SQL语句复用
缓存模块则分为 SQ L语句缓存和查询数据缓存两种由于 MyBatis 需要开发者自定义SQL语句因此 SQL 语句缓存不用考虑而查询数据缓存则被分为一级和二级缓存一级缓存以事务为作用域二级缓存以同一个映射集为作用域而且二级缓存采用直写的方式处理缓存数据被修改和删除的情况。
返回集合时DAO 接口不能写数组例如 User[] 不行得用 List 装载集合如 List<User>。
其他资源
- 入门教程http://www.cnblogs.com/fsjohnhuang/p/4014819.html 、http://www.mybatis.org/spring/zh/index.html
- 学习注解 http://wwww.iteye.com/blog/1235996、http://computerdragon.blog.51cto.com/6235984/1399742
- 结合 Sprin个 http://www.mybatis.org/spring/zh/index.html、http://p.primeton.com/articles/54c1dcc5be20aa3884000012
- 深入原理非常好的博客http://blog.csdn.net/luanlouis文笔流畅
- 在mybatis中使用枚举和boolean提供代码可读性 http://yourenyouyu2008.iteye.com/blog/1971959
框架内调用 MyBatis
/** * Configuration 需要设为 public 以便加入 mapper */ public static Configuration configuration; /** * 一般用法 sqlSessionFactory.openSession()。注意返回的 SqlSession 必须关闭 */ public static SqlSessionFactory sqlSessionFactory; /** * 初始化 MyBatis 数据链接服务 * * @param ds */ public static void init(DataSource ds) { Environment environment = new Environment("development", new JdbcTransactionFactory(), ds); configuration = new Configuration(environment); sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration); // 打印数据库连接路径以便了解 try (Connection conn = environment.getDataSource().getConnection();){ System.out.println("数据库连接字符串" + conn + Constant.ConsoleDiver); } catch (SQLException e) { e.printStackTrace(); } // 如果要观察 MyBatis 动态生成的 SQL 语句请打开控制台的输出。 // org.apache.ibatis.logging.LogFactory.useStdOutLogging(); // org.apache.ibatis.logging.LogFactory.useJdkLogging(); System.out.println("数据库初始化成功" + Constant.ConsoleDiver); } /** * 添加一个 MapperDAO * @param clz */ public static void addDao(Class<? extends BaseDao<?, ?>> clz){ if (clz != null && !configuration.hasMapper(clz)) configuration.addMapper(clz); }
JDBC 4 例子
// https://docs.oracle.com/javase/tutorial/jdbc/basics/cachedrowset.html // https://db.apache.org/derby/docs/10.9/ref/rrefjdbc4_1summary.html // http://download.oracle.com/otn-pub/jcp/jdbc-4_1-mrel-spec/jdbc4.1-fr-spec.pdf public static void create() { try (JdbcRowSet jdbcRs = RowSetProvider.newFactory().createJdbcRowSet();) { // 创建一个 JdbcRowSet 对象配置数据库连接属性 jdbcRs.setUrl("jdbc:derby:helloDB;"); // jdbcRs.setUsername(username); // jdbcRs.setPassword(password); jdbcRs.setCommand("select name from hellotable"); jdbcRs.execute(); while (jdbcRs.next()) { System.out.println(jdbcRs.getString(1)); } // delete the table // s.execute("drop table hellotable"); // System.out.println("Dropped table hellotable"); // rs.close(); // DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException e) { // 通过应用 JDBC 4.0, 您现在不需太多代码即可以获取及遍历异常链在以往的版本中, 您在遍历异常链时必须手工的调用 // getNextException 方法才能得到相同的效果 for (Throwable ex : e) { System.err.println("Error encountered: " + ex); } } }