一.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官方文档上面都有,回头有时间我整理一下.