一、Mybatis简介
1、传统JDBC的不足
我们首先看一下JDBC的一般操作流程。比如,我想从user表中获取根据name获取数据,下面是传统JDBC代码:
package lkb.webchat; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import lkb.webchat.Do.User; public class Test { private static String URL = "jdbc:mysql://localhost:3306/develop"; private static String USER = "root"; private static String PASSWORD = "123456"; /** * 根据用户名查询数据 * @param name * @return */ public static List<User> getUserByName(String name){ List<User> userList = new ArrayList<User>(); Connection connection = null; PreparedStatement pStatement = null; ResultSet resultSet = null; try { //连接驱动 Class.forName("com.mysql.jdbc.Driver"); connection = DriverManager.getConnection(URL, USER, PASSWORD); //sql语句 pStatement = connection.prepareStatement("select * from user where name = ?"); pStatement.setString(1, name); //查询结果 resultSet = pStatement.executeQuery(); while(resultSet.next()){ int id = resultSet.getInt("id"); String password = resultSet.getString("password"); String cellphone = resultSet.getString("cellphone"); int state = resultSet.getInt("state"); //将结果通过set的方式写入自定义的Java类中 User resultUser = new User(); resultUser.setId(id); resultUser.setName(name); resultUser.setPassword(password); resultUser.setCellphone(cellphone); resultUser.setState(state); userList.add(resultUser); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally{ //关闭数据联系 try { if(resultSet != null){ resultSet.close(); } if(pStatement != null){ pStatement.close(); } if(connection != null){ connection.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return userList; } public static void main(String[] args) { List<User> list = getUserByName("lkb"); if(list.size() != 0){ for(User user : list){ System.out.println(user.getName() + " : " + user.getCellphone()); } } } }
下面是最后运行结果:
我们在使用传统的JDBC连接数据库时候需要做以下几件事:
1、注册驱动和数据库信息(用户名和密码),连接数据库,获取connection对象
2、根据connection对象获取statement对象
3、使用statement执行SQL语句(包括设置SQL参数),获取resultSet对象
4、根据获取的resultSet对象,读取数据,转换为POJO对象
5、关闭数据库连接
这个过程非常繁杂,我们需要自己管理一大堆对象(connection statement resultSet),获取的结果也不能自动转换为POJO对象,更为繁琐的是,我们需要自己小心翼翼地关闭数据库连接。
针对这种情况,ORM(Object Relationship Mapping)模型就出现了。简单地说ORM模型就是数据库中的表与POJO类之间的映射模型。我们常说的hibernate、mybatis都是ORM模型框架,只是不同的ORM模型对JDBC的封装程度不一罢了。
2、Mybatis简介
mybatis是一个半自动映射框架。之所以称之为半自动映射框架,是因为,它除了需要提供POJO和映射关系之外,它还需要提供SQL语句。
mybatis前身是ibatis,ibatis是Internet与abatis的组合,是一个基于Java的持久层框架。
mybatis需要提供的映射文件包含以下三个部分:
1/ POJO
2/ 映射关系
3/ SQL语句
与hibernate不同,它需要自己书写sql语句,这样也提供了一定的灵活性,同时mybatis也可以书写动态SQL,这也解决了hibernate表名随时间变化不能动态改变列名的问题。
二、Mybatis简单使用
我们还是以通过name查询user表为例子,说明mybatis的使用。
1、首先,我们建立POJO类。
这个POJO类与数据库中的user表示对应关系(上面已经有建立了)。我们可以手动书写这个POJO,也可以通过mybatis generator这个插件自动完成POJO的书写。这里,我们手动书写。
package lkb.webchat.Do; public class User { private int id; /** * 名称 */ private String name; /** * 密码 */ private String password; /** * 手机号 */ private String cellphone; /** * 登录状态 */ private int state; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getCellphone() { return cellphone; } public void setCellphone(String cellphone) { this.cellphone = cellphone; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getState() { return state; } public void setState(int state) { this.state = state; } }
2、其次,我们书写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="lkb.webchat.Do.User"/> </typeAliases> <!-- 定义数据库信息,默认使用develop数据库构建环境 --> <environments default="develop"> <environment id="develop"> <!-- 采用jdbc事务管理 --> <transactionManager type="JDBC"/> <!-- 配置数据库链接信息 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/develop"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> </configuration>
这里,我们使用一个xml文件来进行配置。我们需要注意的标签有:
1/ typeAliases typeAlias 这两个标签是用来定义别名的
2/ environments environment 这两个表示是用来定义数据库环境的。因为在开发中,我们的数据库环境可以有多个(开发一个环境,测试一个环境,线上又是一个环境)。在environments 中我们可以设置default属性,来表示默认的环境是什么,当需要切换环境时,我们可以直接在此处修改。environment中配置的是数据库环境。其中transactionManager表示事务类型,dataSource标签中配置相关的数据库连接信息。
3、编写Mapper接口。我们之后在Java中就使用该mapper接口进行编程。
package lkb.webchat.mapper; import java.util.List; import lkb.webchat.Do.User; public interface UserMapper {/** * 通过名字获取用户信息 * @param name * @return */ public User getUserByName(String name); }
4、编写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="lkb.webchat.mapper.UserMapper"> <resultMap id="BaseResultMap" type="lkb.webchat.Do.User"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="name" jdbcType="VARCHAR" property="name"/> <result column="password" jdbcType="VARCHAR" property="password"/> <result column="cellphone" jdbcType="VARCHAR" property="cellphone"/> <result column="state" jdbcType="INTEGER" property="state"/> </resultMap> <!-- 根据姓名查询用户信息 --> <select id="getUserByName" parameterType="String" resultMap="BaseResultMap"> select * from user where name = #{name} </select> </mapper>
在这个mapper文件中,我们定义了mapper.java中接口的sql实现。我们需要注意的标签有resultMap(定义一个结果集合)与select(sql语句中的查询)。
在这个mapper.xml文件中,我们通过id与接口方法同名,parameterType传入参数类型,resultMap输入返回结果集合。
当然,这样的mapper.xml文件我们也是需要在mybatis的配置文件中注册的。在mybatis-config.xml文件中增加如下语句,定义一个映射器:
<!-- 定义映射器 --> <mappers> <mapper resource="lkb/webchat/mapper/UserMapper.xml"/> </mappers>
5、最后,在Java中使用mybatis。
package lkb.webchat; 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 lkb.webchat.Do.User; import lkb.webchat.mapper.UserMapper; public class Test2 { private static String RESOURCE = "mybatis_config.xml"; public static void main(String[] args) { SqlSessionFactory sessionFactory = null; SqlSession sqlSession = null; try { sessionFactory = new SqlSessionFactoryBuilder(). build(Resources.getResourceAsStream(RESOURCE)); sqlSession = sessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.getUserByName("lkb"); System.out.println(user.getName() + " : " + user.getCellphone()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { if(sqlSession != null){ sqlSession.close(); } } } }
最后结果如下:
看到上面,我们可能会说,这不是一样要写很多配置文件吗?
其实不然,这些配置文件我们一般只需要在刚开始进行修改。后续一般就是在mapper.java文件中书写接口,在mapper.xml文件中书写sql语句。我们不需要像jdbc时期,每次都需要操控那么多对象。比如,我们新增一个往数据库中添加user对象的功能。我们需要做的就是,在UserMapper.java接口中添加接口方法:
/** * 插入用户信息 * @param user */ public void insertUser(User user);
然后在UserMapper.xml文件中添加对应的sql语句:
<!-- 插入用户信息 --> <insert id="insertUser" parameterType="lkb.webchat.Do.User"> insert into user <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null">id,</if> <if test="name != null">name,</if> <if test="password != null">password,</if> <if test="cellphone != null">cellphone,</if> <if test="state != null">state,</if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null">#{id,jdbcType=INTEGER},</if> <if test="name != null">#{name,jdbcType=VARCHAR},</if> <if test="password != null">#{password,jdbcType=VARCHAR},</if> <if test="cellphone != null">#{cellphone,jdbcType=VARCHAR},</if> <if test="state != null">#{state,jdbcType=VARCHAR},</if> </trim> </insert>
最后在Java文件就可以像使用接口方法一样使用操作数据库,如下:
package lkb.webchat; 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 lkb.webchat.Do.User; import lkb.webchat.mapper.UserMapper; public class Test2 { private static String RESOURCE = "mybatis_config.xml"; public static void main(String[] args) { SqlSessionFactory sessionFactory = null; SqlSession sqlSession = null; try { sessionFactory = new SqlSessionFactoryBuilder(). build(Resources.getResourceAsStream(RESOURCE)); sqlSession = sessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setName("zz"); user.setPassword("123456"); user.setCellphone("17812341234"); user.setState(0); userMapper.insertUser(user); User user2 = userMapper.getUserByName("zz"); System.out.println(user2.getName() + " : " + user2.getCellphone()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { if(sqlSession != null){ sqlSession.close(); } } } }
只需要简单地配置文件,就可以像操作Java类一样操作数据库,这就是mybatis给我们带来的方便之处。