Mybatis入门使用总结

1.什么是Mybatis

Mybatis原来是apache的一个开源项目ibatis,2010年这个项目由apache softwarefoundation迁移到了google code,并且改名为Mybatis。2013年11月迁移到了github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQLMaps和DataAccess Objects(DAO)。Mybatis实际也是一个orm解决方案之一。

2.mybatis入门程序

使程序与Mybatis可以顺利建立连接作为入门程序。

首先需要导入相关jar包:


工程目录,包括后面的程序:


从上图可以看出还需要编写一下log4j.properties便于我们查看日志。

测试连接的小程序:

/*
 * 工具类
 * */
public class MybatisUtil {
	private static ThreadLocal<SqlSession> threadLocal =new ThreadLocal<SqlSession>();
	private static SqlSessionFactory sqlSessionFactory;
	/*
	 * 加载位于src/mybatis.xml配置文件
	 * */
	static{
		try {
			Reader reader =Resources.getResourceAsReader("mybatis.xml");
			sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	//禁止外部访问
	private MybatisUtil(){}
	/*
	 * 获取SqlSession
	 * */
	public static SqlSession getSqlSession(){
		//从当前线程中获取sqlSession对象
		SqlSession sqlSession =threadLocal.get();
		if(sqlSession ==null){
			//如果sqlSessionFactory对象不为空情况下,那么获取SqlSession对象。 
			sqlSession =sqlSessionFactory.openSession();
			//将sqlSession与当前线程绑定在一起
			threadLocal.set(sqlSession);
		}
		//直接返回sqlSession对象
		return sqlSession;
	}
	
	
	/*
	 * 关闭SqlSession与当前线程分离
	 * */
	public static void closeSqlSession(){
		//从当前线程中获取sqlSession对象
		SqlSession sqlSession =threadLocal.get();
		if(sqlSession !=null){
			//关闭sqlSession对象
			sqlSession.close();
			//分开当前线程与sqlSession对象的关系,目的是让GC尽早回收
			threadLocal.remove();
		}
	}
	public static void main(String[] args) {
		Connection conn =MybatisUtil.getSqlSession().getConnection();
		System.out.println(conn !=null ?"连接成功":"连接失败");
		MybatisUtil.closeSqlSession();
	}
}

Mybatis.xml是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>
	
	<!-- 加载类路径下的属性文件 -->
	<properties resource="db.properties"></properties>
	
	<!-- 设置类型别名 -->
	<typeAliases>
		<typeAlias type="cn.spy.model.Student" alias="Student"/>
	</typeAliases>
	
	<environments default="mysql_developer">
		<!-- mysql环境信息 -->
		<environment id="mysql_developer">
			<!-- mybatis使用jdbc事务管理方式 -->
			<transactionManager type="jdbc"></transactionManager>
			<!-- mybatis使用连接池方式来获取连接 -->
			<dataSource type="pooled">
				<!-- 配置与数据库交互的四个必要属性 -->
				<property name="driver" value="${mysql.driver}"/>
				<property name="url" value="${mysql.url}"/>
				<property name="username" value="${mysql.username}"/>
				<property name="password" value="${mysql.password}"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- 加载映射文件 -->
	<mappers>
		<mapper resource="cn\spy\model\StudentMapper.xml"/>
	</mappers>
</configuration>
其实我们完全可以直接Mybatis中数据库必须配置的四个属性的位置,直接配置数据库的驱动,连接,用户名和密码。这样做不便于以后的修改。则直接采用properties文件配置。

db.properties数据库配置文件:

mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/basicjdbc?characterEncoding=utf-8
mysql.username=root
mysql.password=
至于Mybatis.xml中的配置别名和加载Student类的映射配置文件可以暂时忽略,因为此处不用。

运行结果:


阅读上面的代码会发现,其实Mybatis是采用配置文件的形式来配置数据库连接的信息。然后采用Reader的形式去读取配置文件,来获取连接的信息。从而交给SqlSessionFactory来建立连接。第二点就是采用ThreadLocal这么一个类来实现,在我的多线程通信的博文中说过ThreadLocal类主要解决的就是每个线程绑定自己的值,就是用来存储每个线程的私有数据。所以使用ThreadLocal就是把当前线程与SqlSession对象绑定一起了。然后作为工具类实现了一个获取连接和关闭连接的方法,便于后面使用。

3.Mybatis实现CRUD

pojo(Student):

public class Student {
	private Integer id;
	private String name;
	private double sal;
	public Student(){}
	public Student(Integer id, String name, double sal) {
		this.id = id;
		this.name = name;
		this.sal = sal;
	}
        
       getter、setter方法......
	
        @Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", sal=" + sal + "]";
	}
}
StudentMapper.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">

<!-- namespace属性是名称空间,必须唯一 -->
<mapper namespace="studentNamespace">
	<!-- resultMap:映射实体与表 
		type属性:表示实体全路径名
		id属性:为实体与表的映射取一个唯一的编号
	-->
	<resultMap type="Student" id="studentMap">
		<!-- id标签:映射主键属性
			result标签:映射非主键属性
			property属性:实体的属性名
			column属性:表的字段名
		 -->
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sal" column="sal"/>
	</resultMap>

	<!-- insert标签:要书写insert这么一个语句
		id属性:为insert这么一个sql语句取一个任意唯一的名字
		parameterType:要执行的dao中的方法的参数,如果是类的话,那么必须使用全路径类。
	 -->
	<insert id="add" parameterType="Student">
		insert into students(id,name,sal) values(#{id},#{name},#{sal});
	</insert>
	
	<!-- 根据id查询学生类 -->
	<select id="findById" parameterType="int" resultType="Student">
		select id,name,sal from students where id=#{id};
	</select>
	
	<!-- 查询所有的学生类 
		理论上resultType要写List<Student>
		但这里只需书写List中的类型即可,即只需书写Student的全路径名
	-->
	<select id="findAll" resultType="Student">
		select * from students;
	</select>
	
	<!-- 更新学生表记录 -->
	<update id="update" parameterType="Student">
		update students set name=#{name},sal=#{sal} where id=#{id};
	</update>
	
	<!-- 删除学生记录 -->
	<delete id="delete" parameterType="Student">
		delete from students where id=#{id};
	</delete>
</mapper>
解释:Mybatis采用模型对象的映射文件,作为数据库操作语句的对象。使用resultMap这个标签来封装。至于说明都在代码的注释上,如果还有不明白,那么可以看Mybatis文档给出了例子。。

由于Mybatis是一个orm框架,所以必然是作为数据库操作的一个框架。那么对应还需要dao层的代码。

dao接口:

public interface IStudentDao {

	public void add(Student student) throws Exception;
	public void delete(Student student) throws Exception;
	public void update(Student student) throws Exception;
	public Student selectOneById(int id) throws Exception;
	public List<Student> selectAll() throws Exception; 
}

dao实现类:

public class StudentDaoImpl implements IStudentDao{

	@Override
	public void add(Student student) throws Exception {
		// TODO Auto-generated method stub
		SqlSession sqlSession =null;
		try{
			sqlSession =MybatisUtil.getSqlSession();
			//开启事务
			//读取StudentMapper.xml映射文件中的SQL语句
			sqlSession.insert("studentNamespace.add",student);
			//事务提交
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			//事务回滚
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}

	@Override
	public void delete(Student student) throws Exception {
		SqlSession sqlSession =null;
		try{
			sqlSession =MybatisUtil.getSqlSession();
			//开启事务
			//读取StudentMapper.xml映射文件中的SQL语句
			sqlSession.delete("studentNamespace.delete",student);
			//事务提交
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			//事务回滚
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}

	@Override
	public void update(Student student) throws Exception {
		SqlSession sqlSession =null;
		try{
			sqlSession =MybatisUtil.getSqlSession();
			sqlSession.update("studentNamespace.update",student);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			//事务回滚
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
		
	}

	@Override
	public Student selectOneById(int id) throws Exception {
		SqlSession sqlSession =null;
		try{
			sqlSession =MybatisUtil.getSqlSession();
			Student student =sqlSession.selectOne("studentNamespace.findById", id);
			sqlSession.commit();
			return student;
		}catch(Exception e){
			e.printStackTrace();
			//事务回滚
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}

	@Override
	public List<Student> selectAll() throws Exception {
		SqlSession sqlSession =null;
		try{
			sqlSession =MybatisUtil.getSqlSession();
			return sqlSession.selectList("studentNamespace.findAll");
		}catch(Exception e){
			e.printStackTrace();
			//事务回滚
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
}

解释:发现获取连接和释放连接都是采用之前写的例子Mybatis工具类。然后获取到sqlSession对象。通过sqlSession做操作。对于操作方法中第一个参数的解释:名称空间.配置文件操作标签的id。这样就使sqlSession可以找到StudentsMapper对应的sql语句。而从配置文件中也可以大概分析出采用了模板方法模式。虽然crud都是一套固定的标签,然而每一个使用者用到sql语句可能会不同,由于每个人需要的查询不同,并且可以得到需要的不同查询结果。

注意:

在同样的程序中为什么我的程序却跑不起来呢。需要一点配置在Mybatis.xml总配置文件中。

   配置StudentMapper映射,让Mybatis.xml加载:

<!-- 加载映射文件 -->
	<mappers>
		<mapper resource="cn\spy\model\StudentMapper.xml"/>
	</mappers>
细节在入门例子中有配置。

   然而mybatis.xml配置文件中使用别名的配置是为了简化开发,减少写太长的类路径。

4.Mybatis实现分页

pojo类、mybatis.xml等前面例子一样的。主要是StudentMapper.xml、dao实现类的编写。

StudentMapper.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">

<!-- namespace属性是名称空间,必须唯一 -->
<mapper namespace="studentNamespace">
	<!-- resultMap:映射实体与表 
		type属性:表示实体全路径名
		id属性:为实体与表的映射取一个唯一的编号
	-->
	<resultMap type="Student" id="studentMap">
		<!-- id标签:映射主键属性
			result标签:映射非主键属性
			property属性:实体的属性名
			column属性:表的字段名
		 -->
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sal" column="sal"/>
	</resultMap>
       <!-- 分页查询学生记录 -->
    <select id="selectByPaging" parameterType="map" resultMap="studentMap">
        select id,name,sal from students limit #{pstart},#{psize};
    </select>
</mapper>

dao接口:

public interface IStudentDao {
    public List<Student> selectByPaging(int start ,int size) throws Exception;
}

dao实现类:

public class StudentDaoImpl implements IStudentDao{
      @Override
    public List<Student> selectByPaging(int start ,int size) throws Exception {
        SqlSession sqlSession =null;
        try{
            sqlSession =MybatisUtil.getSqlSession();
            Map<String,Object> map =new LinkedHashMap<String,Object>();
            map.put("pstart", start);
            map.put("psize", size);
            return sqlSession.selectList("studentNamespace.selectByPaging", map);
        }catch(Exception e){
            e.printStackTrace();
            //事务回滚
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
} 
测试:

public static void main(String[] args) throws Exception {
	      IStudentDao studentDao =new StudentDaoImpl();
              System.out.println("-------------第一页");
        List<Student> list1 =studentDao.selectByPaging(0, 4);
        for(Student stu:list1){
            System.out.println(stu);
        }
}
结果:


数据库:


解释:Mybatis主要就是使用sql语句进行操作的。而mysql对于分页查询提供了limit关键字,方便了查询。而传入的第几条记录开始和每页显示的记录数,使用map传入。而StudentMapper.xml中使用

parameterType="map" resultMap="studentMap"
来传参和设置返回结果。

5.Mybatis实现有条件分页查询

有条件分页查询,就是使用分页查询,但是使用了条件进行过滤,而我此处玩下模糊查询做为条件。

StudentMapper.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">

<!-- namespace属性是名称空间,必须唯一 -->
<mapper namespace="studentNamespace">
	<!-- resultMap:映射实体与表 
		type属性:表示实体全路径名
		id属性:为实体与表的映射取一个唯一的编号
	-->
	<resultMap type="Student" id="studentMap">
		<!-- id标签:映射主键属性
			result标签:映射非主键属性
			property属性:实体的属性名
			column属性:表的字段名
		 -->
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sal" column="sal"/>
	</resultMap>
       <!-- 有条件分页 -->
    <select id="selectByConditionalPaging" parameterType="map" resultMap="studentMap">
        select id,name,sal from students where name like #{pname} limit #{pstart},#{psize};
    </select>
</mapper> 
dao接口:

public interface IStudentDao {
       public List<Student> selectByConditionalPaging(String name ,int start ,int size) throws Exception;
}
dao实现类:

public class StudentDaoImpl implements IStudentDao{
      @Override
    public List<Student> selectByConditionalPaging(String name, int start,
            int size) throws Exception {
        SqlSession sqlSession =null;
        try{
            sqlSession =MybatisUtil.getSqlSession();
            Map<String,Object> map =new LinkedHashMap<String,Object>();
            map.put("pname", "%"+name+"%");
            map.put("pstart", start);
            map.put("psize", size);
            return sqlSession.selectList("studentNamespace.selectByConditionalPaging", map);
        }catch(Exception e){
            e.printStackTrace();
            //事务回滚
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
}
测试:

public static void main(String[] args) throws Exception {
	IStudentDao studentDao =new StudentDaoImpl();
        System.out.println("-------------第一页");
     List<Student> list1 =studentDao.selectByConditionalPaging("魏大勋", 0, 4);
     for(Student stu:list1){
        System.out.println(stu);
     }
}
结果:


6.Mybatis工作流程

(1)通过Reader对象读取src目录下的mybatis.xml配置文件(该文本的位置和名字可任意)

(2)通过SqlSessionFactoryBuilder对象创建SqlSessionFactory对象

(3)从当前线程中获取SqlSession对象

(4)事务开始,在mybatis中默认

(5)通过SqlSession对象读取StudentMapper.xml映射文件中的操作编号,从而读取sql语句

(6)事务提交,必写

(7)关闭SqlSession对象,并且分开当前线程与SqlSession对象,让GC尽早回收

-----------------------------------------


至于Mybatis的两个配置文件,上面都有注解就不再赘述了。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值