一.Hibernate与Mybatis的区别
持久层框架用的最多的就是Hibernate和Mybatis了.其中Hibernate了.Hibernate其实就是让使用者直接对pojo进行操作,然后会将对pojo的操作通过Hibernate提供的方法完成到数据库表中对应的相关操作.程序员甚至都不用写sql.但是Mybatis实际上对把对pojo对象的操作映射到sql语句.所以Mybatis相对于Hibernate更简单,学习成本更低.
二.初步使用Mybatis
由于我也只是才学习Mybatis的使用,所以关于源码部分就不说了.直接上代码.
2.1配置Mybatis的配置配置
<?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.lubby.bean.User" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="org.postgresql.Driver" /> <property name="url" value="jdbc:postgresql://localhost:5432/postgres" /> <property name="username" value="postgres" /> <property name="password" value="admin" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/lubby/dao/mapper/UserDAOMapper.xml" /> </mappers> </configuration>
这里面比较重要的部分是
<enviroments>里面要配置数据库连接相关数据.
<mapper> 引入Mapper.xml文件
<typeAliases>设置别名,用在Mapper.xml文件中resultType或者是parameterType中使用.
2.2 pojo (为了篇幅,setter,getter方法就省略了) 和对应的数据库表
CREATE TABLE t_user ( user_id INTEGER DEFAULT nextval('t_user_user_id_seq'::regclass) NOT NULL, user_name CHARACTER VARYING(40) NOT NULL, password CHARACTER VARYING(40) NOT NULL, nick_name CHARACTER VARYING(40), gender CHARACTER VARYING(4), address CHARACTER VARYING(40), nation CHARACTER VARYING(40), PRIMARY KEY (user_id) );
public class User { private String userId; private String userName; private String password; private String nickName; private String gender; private String address; private String nation; public User() { super(); // TODO Auto-generated constructor stub } public User(String userId, String userName, String password, String nickName, String gender, String address, String nation) { super(); this.userId = userId; this.userName = userName; this.password = password; this.nickName = nickName; this.gender = gender; this.address = address; this.nation = nation; } }
2.3 mapper文件
<mapper namespace="com.lubby.dao.UserDAO"> <resultMap type="com.lubby.bean.User" id="userResult"> <result column="user_id" property="userId"/> <result column="user_name" property="userName"/> <result column="password" property="password"/> <result column="nick_name" property="nickName"/> <result column="gender" property="gender"/> <result column="address" property="address"/> <result column="nation" property="nation"/> </resultMap> <parameterMap type="com.lubby.bean.User" id="userParameter"> <parameter resultMap="user_id" property="userId" /> <parameter resultMap="user_name" property="userName" /> <parameter resultMap="password" property="password" /> <parameter resultMap="nick_name" property="nickName" /> <parameter resultMap="gender" property="gender" /> <parameter resultMap="address" property="address" /> <parameter resultMap="nation" property="nation" /> </parameterMap> <select id="getUserByUserName" parameterType="String" resultMap="userResult"> select * from t_user where user_name = #{userName} </select> <select id="getUserCount" resultType="integer"> select count(*) from t_user </select> <delete id="deleteByUserName" parameterType="String"> delete from t_user where user_name = #{userName} </delete> <update id="updateByUserName" parameterType="map"> update t_user set nick_name = #{nickName} where user_name = #{userName} </update> <insert id="insert" parameterMap="userParameter"> insert into t_user (user_id,user_name,password,nick_name,gender,address,nation) values(#{userId , typeHandler=com.lubby.typehandler.IntegerTypeHandler},#{userName},#{password},#{nickName},#{gender},#{address},#{nation}) </insert> </mapper>
所有的操作都是依据这个mapper文件进行的,sql写在mapper文件当中.然后通过调用mapper的id来使用相关数据库操作.
<mapper namespace="com.lubby.dao.UserDAO"> 作为区别操作的的命名空间,在使用interface+mapper操作的时候namespace必须是interface的全限定名(包名+类名).
<select> <delete> <update><insert>是用来写具体sql操作的.其中最重要的几个几个属性必须要搞清楚.
id :作为同一个mapper下调用的名称,如果使用interface+mapper的时候这个id必须要和interface中的方法要一样.通过namespace+id可以唯一的确定一个sql操作.
parameterType: sql入参,可以为java基本类型,jdk中java类或者自定义的java类.如果使用自定义的java类最好在Mybatis配置文件中设置别名,这里可以直接使用别名.
parameterMap: sql入参当pojo类中属性名和数据库字段名不一样的时候,parameterType就无能为力了,需要使用parameterMap来对pojo类的属性名转成数据库字段名.子元素<result>中属性resultMap是数据库字段名,property是pojo属性名.
resultType: sql返回结果类型,可以为java基本类型,jdk中java类或者自定义的java类,如果使用自定义的java类最好在Mybatis配置文件中设置别名,.如果结果中某些字段pojo没有也不会报错,如果pojo中有某些字段,而sql返回结果中有,也不会报错.只是这些字段不被赋值.
resultMap: sql返回结果类型.当pojo中某些属性名和数据库中字段名不一样,resultType就无能为力,所以需要resultMap来对pojo类的属性名转换成数据库字段名.
2.4 调用sql语句
public class Test { public static SqlSessionFactory sqlSessionFactory; public static Reader reader; static{ try { //加载Mybatis配置文件 reader = Resources.getResourceAsReader("config/MybatisConfiguration.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { //获取mybatis 的sqlsession对象 SqlSession session = sqlSessionFactory.openSession(); //这些操作都是通过(mapper的namespace+方法名称) 和入参来调用 User user = session.selectOne("com.lubby.dao.UserDAO.getUserByUserName", "admin11"); int count = session.selectOne("com.lubby.dao.UserDAO.getUserCount"); int result = session.delete("com.lubby.dao.UserDAO.deleteByUserName", "admin333"); Map<String, String> parameters = new HashMap<String, String>(); parameters.put("nickName", "11"); parameters.put("userName", "admin1"); session.update("com.lubby.dao.UserDAO.updateByUserName", parameters); User insertUser = new User("204", "admin", "admin", "admin", "Male", "南京", "中国"); session.insert("com.lubby.dao.UserDAO.insert", insertUser); session.commit(); System.out.println("count : " + count); System.out.println(result); System.out.println(user); } }
通过SqlSession对象来执行相关sql.这里通过namespace+sql的id来定位调用那个sql.这里事务默认不是自动提交的,最后要提交以下事务.
Mybatis最常用的调用sql的方法是通过Interface+Mapper文件来调用,这样就可以通过对接口方法的调用转化成对sql的调用,更简单,所以提倡使用这种Interface+Mapper的方式.
只需要添加一个接口
public interface UserDAO { public User getUserByUserName(String userName); public int getUserCount(); public int deleteByUserName(String userName); public int updateByUserName(String userName); public int insert(User user); }
然后mapper中namespace必须要是接口的全限定名,这样Interface和Mapper就绑定起来了.
调用方法
public class Test2 { public static SqlSessionFactory sqlSessionFactory; public static Reader reader; static{ try { //加载Mybatis配置文件 reader = Resources.getResourceAsReader("config/MybatisConfiguration.xml"); //创建SqlSessionFactory对象 sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args){ //获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //通过接口调用相关sql UserDAO userDAO = sqlSession.getMapper(UserDAO.class); int count = userDAO.getUserCount(); User user = userDAO.getUserByUserName("admin1"); System.out.println(count); System.out.println(user); } }
这样写sql的只要写好sql定义好接口,别人就能直接使用了,不用管mapper了.
三.类型转换扩展
如果你的pojo类属性类型不能自动转换成数据库类型,没关系,Mybatis提供了TypeHandler类,我们只要继承TypeHandler类然后实现几个方法,相关类型转换自己在实现的类里面去做处理就可以了.
自己扩展的TypeHandler
public class IntegerTypeHandler implements TypeHandler<String> { @Override public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { Integer value = Integer.valueOf(parameter); ps.setInt(i, value); } @Override public String getResult(ResultSet rs, String columnName) throws SQLException { // TODO Auto-generated method stub return null; } @Override public String getResult(ResultSet rs, int columnIndex) throws SQLException { // TODO Auto-generated method stub return null; } @Override public String getResult(CallableStatement cs, int columnIndex) throws SQLException { // TODO Auto-generated method stub return null; } }
里面的几个方法根据方法名称应该就知道是什么意思了吧,这个demo我只实现了一个入参类型转换的方法,就是把String转换成Integer.
mapper中要指定使用类型类型转换
<insert id="insert" parameterMap="userParameter"> insert into t_user (user_id,user_name,password,nick_name,gender,address,nation) values(#{userId , typeHandler=com.lubby.typehandler.IntegerTypeHandler},#{userName},#{password},#{nickName},#{gender},#{address},#{nation}) </insert>
这里指定user_id使用自己扩展的类型转换器#{userId , typeHandler=com.lubby.typehandler.IntegerTypeHandler}
当然Mybatis mapper中有很多标签,在Mybatis官方文档上面都有,回头有时间我整理一下.