Mybatis(一)—— Mybatis的简介及HelloWorld程序

Mybatis学习(一)—— Mybatis的简介及HelloWorld程序

MyBatis的介绍

MyBatis原本是Apache下的一个项目,但是在MyBatis2.0 及 1.0版本的时候,不叫MyBatis,而是叫做IBatis,所以不管是MyBatis还是IBatis,实际上是一回事。是因为在IBatis3.0版本即将推出的时候,这个团队整体的转战到了谷歌旗下,3.0之后就叫做MyBatis了,MyBatis是一个非常优秀的持久化层的半自动框架,和之前接触的JDBC,DBUtil,JdbcTemplate一样,底层都是JDBC原生的技术,是Java连接数据库的标准,DBUtil,JdbcTemplate充其量是一个小工具,不能称之为框架,框架一定是一个整体的解决方案。

原生JDBC的开发流程

操作步骤
  • 加载驱动程序 Class.forName(“驱动类全类名”)
  • 取得数据库连接 Connection conn = DriverManager.getConnection(url,username,password)
  • 编写sql语句
  • 执行sql,操作数据库(Statement / PreparedStatement / ResultSet)
  • 如果是增删改,并且执行多条sql操作,需要进行事务管理
  • 关闭数据库
  • 释放资源
JDBC的缺点
  • 代码冗余:相似的代码到处都是
  • 功能单一:不能完成缓存操作,不能自动的封装结果集
  • 代码耦合度高:所有的sql语句都是写在Java程序中,耦合度高,维护不便

这个时候我们不得不使用工具或者框架,但是工具同样存在以上的问题,所以我们必须使用框架完成持久化层开发

目前比较流行的框架有

  • Hibernate:是一个非常优秀的全自动框架,Hibernate旨在消除sql,意味着一个不懂sql的人,也可以使用Hiberate进行数据访问层开发,在开发过程中,完全针对的是实体类的对象,比如创建一个对象,save(对象),这个对象就通过ORM映射关系保存到表中,但是Hibernate存在问题是
    ① 不需要编写sql,所以一些复杂的查询由Hibernate自动生成sql,不能进行优化,
    ② 对于复杂查询来说我们还需要编写另外的一种语句叫做HQL,所以学习成本增加,
    ③ Hibernate不许程序员编写sql,而是由Hibernate自动的生成sql,所以执行效率比较低。
  • JAP+SpringData:和Hibernate几乎一样。
  • MyBaits:是一个非常优秀的半自动框架,不像Hibernate那样进行黑箱操作,而是将sql的编写交个程序员,而且sql也不用编写在Java程序中,而是使用xml配置方式编写sql语句,所以Mybais的特点:
    ① sql与Java代码相分离,
    ② SQL语句是程序员编写,可以进行更好的优化,
    ③ 除了已经学过的sql之前,不会像Hibernate那样学其他的QL语句。

Mybatis HelloWorld

步骤如下:

①:创建Java工程:MyBatis01

②:加入jar包
mybatis-3.4.1.jar
mysql-connector-java-5.1.37-bin.jar

③:使用ssm数据库中的emp表

④:创建对应的实体类

⑤:为了更加方便的输出MyBatis的日志,我们加入log4j配置和jar包
log4j.xml和log4j.jar

⑥:现在基础环境已经搭建好了,接下来就是MyBatis的配置

⑦:创建MyBatis的全局配置文件

mybatis-config.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>
	<environments default="mysql">
		<environment id="mysql">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql:///ssm" />
				<property name="username" value="root" />
				<property name="password" value="a123456" />
			</dataSource>
		</environment>
	</environments>
	<!-- 注册sql映射文件 -->
	<mappers>
		<mapper resource="com/zym/dao/EmpDao.xml" />
	</mappers>
</configuration>

⑧:创建Emp表的sql映射文件,同时将SQL映射文件注册到全局配置文件中
EmpDao.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="com.wanbangee.dao.EmpDao">
	 <select id="selectEmp" resultType="com.zym.entities.Emp">
	 	select * from emp 
	 </select>
</mapper>

⑨:测试

	@Test
	public void testEmpQuery() throws Exception {
		
		//获取全局配置文件文件的字节输入流
		InputStream input = Resources.getResourceAsStream("mybatis-conf.xml");
		//创建SqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		//获取SQLSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();
		//调用dao
		List<Emp> emps = sqlSession.selectList("com.zym.dao.EmpDao.selectEmp", null);
		
		System.out.println(emps);
		
		sqlSession.close();
	}

上面测试的查询结果集的数据都为null,这是什么原因呢?因为MyBatis3.4.1 默认的自动驼峰没有开启,需要我们手动开启。在MyBatis全局配置文件中添加。

<configuration>

	<settings>
		<!-- 设置自动驼峰命名 -->
		<setting name="mapUnderscoreToCamelCase" value="true"></setting>
	</settings>
	
	<environments default="mysql">
		<environment id="mysql">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql:///ssm" />
				<property name="username" value="root" />
				<property name="password" value="a123456" />
			</dataSource>
		</environment>
	</environments>
	<!-- 注册sql映射文件 -->
	<mappers>
		<mapper resource="com/zym/dao/EmpDao.xml" />
	</mappers>
</configuration>

MyBatis中的接口式编程(开发中最常用的)

在原始的MVC开发中,我们编写DAO层时,使用dao接口+dao实现类的形式,例如,一般都在com.xxx.dao包下写IEmpDao的接口,在com.xxx.dao。impl包下写IEmpDao的接口的实现类EmpDaoImpl,但在MyBatis中,可以不用编写实现类,直接写dao接口,该接口的实现会由MyBatis使用动态代理的形式实现

测试案例

编写根据ID查询Emp的sql语句及测试:

  <select id="selectEmpByEmpId" resultType="com.wanbangee.entities.Emp">
 	select * from emp where emp_id = #{id}
 </select>
@Test
	public void testSelectEmpByEmpId() throws Exception {
		
		//获取全局配置文件文件的字节输入流
		InputStream input = Resources.getResourceAsStream("mybatis-conf.xml");
		//创建SqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		//获取SQLSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();
		
		Emp emp = sqlSession.selectOne("com.zym.dao.EmpDao.selectEmpByEmpId", 1);
		
		System.out.println(emp);
		
		sqlSession.close();
	}

以上的程序,会不会出现问题呢?当然会有问题,我们没有办法指定传入sql的参数类型,可以随意传递任意类型,但是结果却差强人意。而且在开中也存在问题,所谓三层架构,Service层如何调用sql呢?
所以我们要使用接口式编程:

  • 定义数据访问层接口
  • 将数据访问层接口和sql映射文件相绑定
  • 将接口的每个方法和sql映射文件中的每一条sql语句相绑定

①:定义接口

public interface EmpDao {

	public List<Emp> selectEmp();
	
	public Emp selectEmpByEmpId(Integer empId);
	
	public void insertEmp(Emp emp);
	
	public void deleteEmp(Integer empId);
	
}

②:定义此接口的sql映射文件(实现简单的CRUD)

<?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 : 表示此xml是sql映射文件
 		namespace : 命名空间,表示此sql映射文件是和那个DAO接口对应的
  -->
<mapper namespace="com.zym.dao.EmpDao">

	<!-- public List<Emp> selectEmp(); 
	-->
	<select id="selectEmp" resultType="com.zym.entities.Emp">
		select * from emp 
	</select>
	
	
	<!-- 
		public Emp selectEmpByEmpId(Integer empId);
		 select : 表示此方法进行的查询操作
		 	id : sql的ID,必须和对应接口中的一个方法名绑定,表示此条sql就是这个方法的sql语句
		 	resultType : 表示的是方法的返回值类型(全类名),如果返回值类型是List,那么只需要编写List中存放对象的全类名即可
		 	parameterType : 参数类型,一般情况下,此属性可以省略不写,表示指定传入参数的类型
		 sql中的#{} 是表示sql以预处理的形式,使用?作为占位符执行sql,
		 如果传入的参数是一个普通的参数【基本数据类型,及包装类对象,或者字符串】,那么#{内容}
	 -->
	<select id="selectEmpByEmpId" resultType="com.zym.entities.Emp">
		select * from emp where emp_id = #{empId}
	</select>
	
	<!-- 
		public void insertEmp(Emp emp);
		如果传入的参数为实体类的对象,那么在sql中,必须使用#{实体类JavaBean风格的属性名} 进行参数绑定
	 -->
	 <insert id = "insertEmp">
	 	insert into emp(emp_name,emp_mail,emp_gender,dept_id) values(#{empName},#{empMail},#{empGender},#{deptId})
	 </insert>
	 
	 <!-- 
	 	public void deleteEmp(Integer empId)
	  -->
	 <delete id="deleteEmp">
	 	delete from emp where emp_id = #{empId}
	 </delete>
	
</mapper>

③:测试

	public void testEmpQuery() throws Exception {

		// 获取全局配置文件文件的字节输入流
		InputStream input = Resources.getResourceAsStream("mybatis-conf.xml");
		// 创建SqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 获取SQLSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// List<Emp> emps = sqlSession.selectList("com.wanbangee.dao.EmpDao.selectEmp",
		// null);//非接口式编程

		// 接口式编程
		// ① 获取接口的实现类对象(通过动态代理完成)
		EmpDao empDao = sqlSession.getMapper(EmpDao.class);
		// ② 调用接口方法
		List<Emp> emps = empDao.selectEmp();// 调用接口方法

		System.out.println(emps);

		sqlSession.close();
	}

	@Test
	public void testSelectEmpByEmpId() throws Exception {

		// 获取全局配置文件文件的字节输入流
		InputStream input = Resources.getResourceAsStream("mybatis-conf.xml");
		// 创建SqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 获取SQLSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// Emp emp = sqlSession.selectOne("com.wanbangee.dao.EmpDao.selectEmpByEmpId", 1);
		// 接口式编程
		// ① 获取接口的实现类对象(通过动态代理完成)
		EmpDao empDao = sqlSession.getMapper(EmpDao.class);
		// ② 调用接口方法
		Emp emp = empDao.selectEmpByEmpId(1);
		System.out.println(emp);

		sqlSession.close();
	}
	
	@Test
	public void testInsertEmp() throws Exception {

		// 获取全局配置文件文件的字节输入流
		InputStream input = Resources.getResourceAsStream("mybatis-conf.xml");
		// 创建SqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 获取SQLSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// Emp emp = sqlSession.selectOne("com.wanbangee.dao.EmpDao.selectEmpByEmpId", 1);
		// 接口式编程
		// ① 获取接口的实现类对象(通过动态代理完成)
		EmpDao empDao = sqlSession.getMapper(EmpDao.class);
		// ② 调用接口方法
		Emp emp = new Emp();
		emp.setEmpName("AABB");
		emp.setEmpMail("aabb@163.com");
		empDao.insertEmp(emp);
		sqlSession.commit();
		sqlSession.close();
	}
	
	@Test
	public void testDeleteEmp() throws Exception {

		// 获取全局配置文件文件的字节输入流
		InputStream input = Resources.getResourceAsStream("mybatis-conf.xml");
		// 创建SqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 获取SQLSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// Emp emp = sqlSession.selectOne("com.wanbangee.dao.EmpDao.selectEmpByEmpId", 1);
		// 接口式编程
		// ① 获取接口的实现类对象(通过动态代理完成)
		EmpDao empDao = sqlSession.getMapper(EmpDao.class);
		// ② 调用接口方法
		empDao.deleteEmp(11);
		sqlSession.commit();
		sqlSession.close();
	}

以上就是接口式编程,在开发中,实际上也是全部使用接口式编程完成,有很多优点:

  • 解耦合,java代码和sql已经分离了,而且数据访问层有实际的接口存在,整合Spring的时候,就可以将数据访问层加入到IOC容器中了
  • 入参为指定类型,调用方法的时候,参数的类型不能任意了,必须符合接口定义的方法的入参的标准

总结

  1. 接口式编程
    原生:DAO----》DAOImpl
    Mybatis:Dao—》Dao.xml
  2. SqlSession表示的是和数据库的一次会话,所以用完必须关闭
  3. SqlSession和Connection一样,都是非线程安全的,所以每次的操作必须重新的获取对象。
  4. 一张表 ----- 一个 实体类 ----- 一个Dao.java ----- 一个Dao.xml
  5. Dao接口是没有实现类的,但是Mybatis会给这个接口生成一个代理对象(需要将接口和映射文件进行绑定)
  6. 两个重要的配置文件:
    · Mybatis的全局配置文件:包含了数据库的连接信息,也可以包含事务管理,系统的运行环境等等
    · sql映射文件:保存了每一条sql语句的映射信息,这个文件就是将sql抽取出来的保存的文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值