From Hibernate To Mybatis (一)
前言
新公司新项目的持久层用到了Mybatis,在此之前的一两年我一直使用的是Hibernate,关于这两个框架的争议一直存在,有人说Hibernate过于臃肿效率低于Mybatis,也有人说Hibernate优化做的好效率一样很棒,其实我还是认为各有优势的,比如Hibernate的API可以让我们无视数据库移植,HQL也简化了SQL,但Mybatis的灵活性确实略高于Hibernate,只要不是用JDBC,这些个框架整体上应当都是差不多的,无非就是用的好用的坏的问题。刚进公司那阵鸿洋曾经告诉过我,会Hibernate的话学Mybatis也就是几个小时的事情,看来确实如此,不管是整体的架构或者使用方法上都是同出一辙,本篇blog是我学习Mybatis的第一篇,所以就写一个简单的CRUD,当然我的这一系列blog还有一个特点就是会不断和hibernate做比较,一边总结回顾Hibernate,一边学习记录Mybatis。
初识MyBatis
首先看一下Mybatis的工程结构,
给我的第一感觉就是轻量级,jar包只需要2个,并无任何依赖,那么再来看看Hibernate的工程结构,
相比之下,孰“轻”孰“重”一目了然。再具体观察一下包的结构,不难发现Mybatis下有一个mappers包,里面放的是xml文件,没学过应该也听说过Mybatis的SQL语句是独立写在配置文件中的,并且正是写在这些mapper.xml文件中的,这个后面再细说。不管哪个框架自然应当有一个整体的配置文件,就像Hibernate中的hibernate.cfg.xml一样,我们来看看Mybatis的mybatis-config.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <typeAlias alias="User" type="com.wl.entity.User" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/testdb2" /> <property name="username" value="root" /> <property name="password" value="11fit" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/wl/mappers/user_mapper.xml" /> </mappers> </configuration>
基本上和Hibernate的配置方法完全一致,数据源、mapper文件(hbm文件),唯独需要注意的一点是这里配置了一个<typeAliases>,这个配置也很好理解,就是为我们的实体Bean配置了一个别名,在后面的mapper.xml中如果需要引入User的话我们就不用带包名了,否则必须写完整的包名+类名。
下面重点内容就是实体类和mapper文件,在Hibernate中,我们的实体类必然会有一个映射文件(hbm.xml)或映射注解(@Entity @Table)相对应,它们声明了我们实体Bean的属性和数据库字段的对应方式、数据类型等等,而在Mybatis中,依旧如此,并且除了这些,Mybatis还将SQL语句也放进了这种配置文件中。下面我们就看看user_mapper.xml这个配置文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.wl.entity.UserMapper"> <!--通过<resultMap>映射实体类属性名和表的字段名对应关系 --> <resultMap type="User" id="userResultMap"> <!-- 用id属性来映射主键字段 --> <id property="id" column="userId" /> <result property="name" column="userName" /> <result property="pwd" column="userPwd" /> <result property="birthday" column="userBorn" /> </resultMap> <select id="selectUserByID" parameterType="int" resultMap="userResultMap"> select * from t_user where userId = #{id} </select> <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="userId"> insert into t_user(userName,userPwd,userBorn) values(#{name},#{pwd},#{birthday}) </insert> <delete id="deleteUser" parameterType="int"> delete from t_user where userId = #{id} </delete> <update id="updateUser" parameterType="User"> update t_user set userName = #{name} where userId = #{id} </update> </mapper>
首先来整体看一下,最上面的<resultMap>的配置非常类似于Hibernate中hibernate-mapping的配置,随便找一个Hibernate的hbm文件来看看:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.wl.entity"> <class name="IDCard" table="t_id_card"> <id name="id" column="card_id"> <generator class="native" /> </id> <property name="number" /> <many-to-one name="person" column="pid" unique="true"></many-to-one> </class> </hibernate-mapping>
<select id="selectUserByID" parameterType="int" resultMap="userResultMap">
不难发现,每一个SQL语句都有一个id,它就是我们调用这条SQL的唯一凭证,再看看最外层的<mapper>中还有一个namespaces的配置,如果我们配置了这个命名空间,那么我们在调用SQL的时候就需要通过命名空间.SQL_ID的组合字符串作为键去调用了。
第二个配置参数是parameterType,顾名思义自然就是参数类型了,这个没什么好说的。
第三个配置参数是resultMap,这个就是重点配置了,回头看看这里引用的“userReultMap”是在哪里定义的?没错,正是在配置文件的最顶端定义的那个和Hibernate映射配置类似的resultMap,配置它的作用就是保证查询字段和实体属性相对应。在Hibernate中我们就是通过配置<property name="xxx"/ cloumn="t_xxx">来保证ORM映射一致,而在Mybatis中依旧如此。当然我们也可以不用配置这个resultMap,那么我们必须在SQL中指定查询字段的别名,以保证和实体Bean中的属性名一致。在resultMap中的type和sql配置中的parameterType中,我们都是直接用的“User”,这里没有加包名自然就归功于我们之前配置的那个<typeAliases>。
还有一点我认为都不用说了,就是SQL语句中的占位符,Hibernate是通过 ? 或者 :param 来占位的,而Mybatis是在SQL语句中通过 #{xxx}来占位的。 这里仅仅讲解了<select>的标准参数配置和含义,如果用到其它的相关配置在官方文档必然有详尽的记录。好了,最后就该写我们的测试类了,并看看我们是如何启动Mybatis又如何去调用SQL语句的:
package com.wl.test; import static org.junit.Assert.fail; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import com.wl.entity.User; public class Test { private static SqlSessionFactory sqlSessionFactory; private static Reader reader; static { try { reader = Resources.getResourceAsReader("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (Exception e) { e.printStackTrace(); } } public static SqlSessionFactory getSession() { return sqlSessionFactory; } @org.junit.Test public void testQuery() { SqlSession session = sqlSessionFactory.openSession(); try { // 查询 User user = (User) session.selectOne( "com.wl.entity.UserMapper.selectUserByID", 3); System.out.println("id-->" + user.getId()); System.out.println("name-->" + user.getName()); System.out.println("pwd-->" + user.getPwd()); System.out.println("birthday-->" + user.getBirthday()); session.commit(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { session.close(); } } }
是不是和Hibernate很相似呢,Hibernate中的SessionFactory对应这里的SqlSessionFactory,Hibernate中的Session对应这里的SqlSession,包括session的开启关闭,事务的处理都是一模一样,唯独需要注意的是,在Hibernate中我们会在测试的时候再写HQL或SQL语句,而在Mybatis中我们直接通过配置好的SQL的id去调用指定SQL即可,可以看到确实是通过“命名空间.SQL_ID“的方式去调用的,最后看一下运行结果:
可以看到成功运行,没有任何问题,而增删改也都是类似的,下面只贴出核心代码:
// 新增 // User user = new User(); // user.setName("jack"); // user.setPwd(111); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // user.setBirthday(sdf.parse("1992-08-29")); // session.insert("com.wl.entity.UserMapper.insertUser", user); // 删除 // session.delete("com.wl.entity.UserMapper.deleteUser", 1); // 更新 // User user = (User) session.selectOne( // "com.wl.entity.UserMapper.selectUserByID", 25); // user.setName("harry"); // session.update("com.wl.entity.UserMapper.updateUser", user);
总结
这是学习Mybatis的第一课,仅仅是一些最基本的操作,开发技术上都是相似相通的,而且都是为我们的产品或项目服务的一种工具而已,所以不论Hibernate或者Mybatis,只要效率OK,都是可取的,每一种框架都具备其设计的艺术和美感,我认为。后续根据学习进度和项目进度情况会继续写Mybatis系列blog,也欢迎各位批评指正,共同交流!同时我自己也会不管追求技术,不断学习,永不止步!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。