因为只学过hibernate没有学mybatis,现在公司需要用到mybatis框架,所以立马在网上找了很多资料快速的学了下mybatis,觉得还行,总体感觉上手挺快,但是要深究还需时日。
MyBatis是什么?
MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。MyBatis的官方下载地址为http://code.google.com/p/mybatis/downloads/list?can=1
测试环境:我使用的是老版本的mybatis-3.0.4.jar+mysql数据库+eclipse的开发工具;
- 加入各种支持包:在项目中添加mybatis和mysql数据库连接支持包,
- mysql表
create table `user` ( `id` double , `user_name` varchar (60), `pass_word` varchar (60) );
- 编写配置文件:mybatis是一个优秀的OR/M框架,他跟hibernate 一样是把实体对象用配置文件或者注解的方式,进行映射,开发人员不必操作繁琐的数据库连接等一些操作,把更多的精力放在代码上。所以现在做的就是编写配置文件;
- 这个是mybatis的总配置文件 SqlMapConfig.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> <properties resource="data.properties" /> <typeAliases> <typeAlias type="com.ucmed.model.User" alias="User" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <mappers> <mapper resource="SqlMap.xml" /> </mappers> </configuration>
- properties resource="data.properties" 引用了外部的.properties的属性文件,通过属性文件对数据源进行配置,此行的意思就是引用外部属性文件
- 在<typeAliases>标签中可以定要多个别名,主要的目的是为了方便其子配置文件mapper.xml的配置,<typeAlias type="com.ucmed.model.User" alias="User" />,User实体类命名为User。
- <environments default="development"><environment id="development">默认的环境,配置文件中可以配置多个环境。
- <transactionManager type="JDBC" /> 事务管理 使用的是JDBC来管理
- <dataSource type="POOLED"> 数据源的配置。
- 最重要的是<mappers>元素,可以把每个mapper看做一行行的sql语句。在<mappers>元素中可以定义多个<mapper resource="UserMap.xml" />的引用。
- 编写UserMap.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0// EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <mapper namespace="com.ucmed.model.User" > <select id="selectUser" parameterType="int" resultType="User"> select * from user where id = #{id} </select> <select id="findUsers" parameterType="map" resultType="User"> select * from user <if test="user_name != null"> where user_name like #{user_name} </if> </select> <insert id="insertUser" parameterType="User" keyProperty="id" useGeneratedKeys="true"> insert into user (id,user_name,pass_word) values (#{id},#{user_name},#{pass_word}) </insert> <update id="updateUser" parameterType="User"> update user set name=#{user_name},pass_word=#{pass_word} where id=#{id} </update> <delete id="deleteUser" parameterType="int"> delete from user where id=#{id} </delete> </mapper>
- 首先看根元素mapper <mapper namespace="com.ucmed.model.User" >定义一个命名空间,这个命名空间一般由类名的全路径来命名用于区分,当然也可以随便取名。
- 在这个xml文件中,有4个关键的标签,分别用于数据的增、删、改、查
- <select id="selectUser" parameterType="int" resultType="User">
select * from user where id = #{id} </select>
以查询为例,每个语句都有一个id,当业务代码调用查询方法时,需要作为参数传入;parameterType为传入的参数类型,传入的参数类型为int 也可以是各种的数据类型,当类型为map时,map中的key必须要和实体类参数名一致,不然查不到;resultType是返回的数据类型; - 在 select id="findUsers" 中可以看到,mybatis也支持动态sql,可以更具传入的参数判断进行动态语句的生成。
- 在<insert>标签中 keyProperty="id" (仅对insert有用)标记一个属性,MyBatis会通过getGeneratedKeys或者通过insert语句的selectKey子元素设置它的值。默认:不设置。
- useGeneratedKeys="true" (仅对insert有用)这会告诉MyBatis使用JDBC的getGeneratedKeys方法来取出由数据(比如:像MySQL和SQL Server这样的数据库管理系统的自动递增字段)内部生成的主键。默认值:false。 这2个属性需要配合使用,如果不使用这两个参数的话,User的id值必须手动设置,而使用这属性后,User的id将会自动生产的方式生成。
- 编写SqlSessionUtil类
package com.ucmed.util; import java.io.IOException; 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; /** * * 获得MyBaits工厂 单例模式 * */ public class MyBatisUtil { private static SqlSessionFactory factory = null; static { try { Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml"); factory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { return factory.openSession(); } }
和hibernate一样,都是需要通过SessionFactory得到session实例,而且处理了一下,使用的是单例模式进行的获取,这样每个session互不干扰。 - 测试:最后就是测试类
package com.ucmed.test; import java.io.IOException; import java.io.Reader; import java.util.HashMap; import java.util.List; import java.util.Map; 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 org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.junit.Test; import com.ucmed.model.User; import com.ucmed.util.MyBatisUtil; /** * * @author Xin * */ public class MyBatisTest { Logger log = LogManager.getLogger(MyBatisTest.class); /** * 按照ID查询 */ @Test public void findOneUserById() { SqlSession session = null; try { // 配置文件 String config = "SqlMapConfig.xml"; Reader reader = Resources.getResourceAsReader(config); // 加载session工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder() .build(reader); session = factory.openSession(); User user = (User)session.selectOne("com.ucmed.model.User.selectUser", 2); System.out.println("用户名为" + user.getUser_name() + " 用户密码:" + user.getPass_word()); } catch (IOException e) { e.printStackTrace(); } finally { if (session != null) { session.close(); } } } /** * 动态查询 * 使用map添加参数 */ @Test public void findUsers(){ SqlSession session = null; try { session = MyBatisUtil.getSqlSession(); Map map = new HashMap(); map.put("user_name", "%t%"); List<User> users = session.selectList(User.class.getName()+".findUsers",map); for (User user : users) { System.out.println("用户名为" + user.getUser_name() + " 用户密码:" + user.getPass_word()); } } finally { if (session != null) { session.close(); } } } /** * 保存对象 */ @Test public void saveUser() { SqlSession session = null; try { session = MyBatisUtil.getSqlSession(); User user = new User(); user.setUser_name("test444444"); user.setPass_word("123"); int count = session.insert("com.ucmed.model.User.insertUser", user); // session.delete("deleteUser",3); session.commit(); if (count <= 0) { System.out.println("插入数据失败"); } else { System.out.println("成功"); System.out.println(user.getId()); session.commit(); } } finally { if (session != null) { session.close(); } } } }
- 总结:通过这两天的自学,觉得mybatis的好处就是,上手蛮快(不知道是不是学过hibernate的原因)。而且看了很多技术文章,mybatis相对于hibernate是小巧的,编写SQL的工作你必须要完成,这样可能会增加你的代码量,但是你可以控制SQL语句,从SQL上进行优化,而Hibernate上手相对慢一些,但是开发速度较快,只要关心业务代码即可,不用把精力放在SQL上,两者的优缺点各有千秋,需要对应项目选择,以上代码或观点如有不对,欢迎指正批评。
补充:
因为mybatis不像hibernate可以在配置文件中使用show_sql来看到sql语句,如果报错想调试sql,可以借助log4j进行日志输出。
log4j.properties:
#将ibatis log4j运行级别调到DEBUG可以在控制台打印出ibatis运行的sql语句 log4j.rootLogger=debug,stdout,logfile ### 把日志信息输出到控制台 ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender #log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout ### 把日志信息输出到文件:jbit.log ### log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=D:/test.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n ###显示SQL语句部分 log4j.logger.com.ibatis=DEBUG log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG