mybatis实现原理及简单的增删改查

1.什么是Mybatis?

MyBatis是一个可以自定义SQL、存储过程和高级映射的持久层框架。

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。

MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。

2.为什么说Mybatis式半自动ORM映射工具?它与全自动的区别在哪里?

Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。

3.优点:

1)MyBatis把sql语句从Java源程序中独立出来,放在单独的XML文件中编写,给程序的维护带来了很大便利。

2)MyBatis封装了底层JDBC API的调用细节,并能自动将结果集转换成Java Bean对象,大大简化了Java数据库编程的重复工作。

3)因为MyBatis需要程序员自己去编写sql语句,程序员可以结合数据库自身的特点灵活控制sql语句,因此能够实现比Hibernate等全自动orm框架更高的查询效率,能够完成复杂查询。

4.Mybatis和Hibernate有哪些不同?

1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

2)Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的缺点是学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。

5.项目例子:

 

创建一个mybatis项目,创建一张学生表

tblstudent      学生表

字段

字段名

类型

长度

是否主键

备注

studentId

学生编号

int

11

Y

自增

studentName

学生姓名

varchar

20

N

 

age

年龄

int

3

N

 

studentNo

学号

varchar

10

N

 

birthDay

生日

Date

0

Y

 

 

  1. 根据studentId查询学生信息,控制台输出
  2. 添加一条学生记录
  3. 根据id修改一条记录, 把原记录中的学生姓名和年龄进行修改,然后查询并在控制台输出。
  4. 根据id删除一条记录。
  5. 根据学生姓名模糊查询学生信息,并在控制台输出

1)数据库表:

create table tblstudent
(
studentId int(11) PRIMARY KEY AUTO_INCREMENT,
studentName varchar(20),
age int(3),
studentNo varchar(10) ,
birthDay Date 
);

INSERT into tblstudent values(NULL,"xxs", 20,"0609170807", "1999-03-24");

2)项目结构:

mybatis实现原理及简单的增删改查

3)配置文件:

mybatis实现原理及简单的增删改查

数据库链接资源文件jdbc.properties:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

日志文件log4j.properties:

log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

配置文件SqlMapConfig.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>
<!-- 加载jdbc.properties -->
<properties resource="jdbc.properties"></properties>

<!-- 配置别名 扫描包 -->
<!-- 通过包扫描,再使用类名时不区分大小写 -->
<typeAliases>
<!-- <typeAlias type="cn.xxs.pojo.User" alias="user"/> -->
 <package name="cn.xxs.pojo"/> 
</typeAliases>

	<!-- environments配置 -->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driverClassName}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<!-- 引入类的配置文件 -->
	<mappers>
	<!-- resource引入sql映射文件 -->
		<!-- <mapper resource="UserMapper.xml"/> -->
		
		<!-- 使用包扫描sql映射文件 -->
		<package name="cn.xxs.mapper"/>
	</mappers>
</configuration>
				

4)实体类:

mybatis实现原理及简单的增删改查

package cn.xxs.pojo;

import java.util.Date;
/**
 * 学生实体类
 * @author xxs
 */
public class Student {
	
	private Integer studentId;//学生编号
	private String studentName;//学生姓名
	private Integer age;//年龄
	private String studentNo;//学号
	private Date birthDay;//生日
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(Integer studentId, String studentName, Integer age, String studentNo, Date birthDay) {
		super();
		this.studentId = studentId;
		this.studentName = studentName;
		this.age = age;
		this.studentNo = studentNo;
		this.birthDay = birthDay;
	}
	public Integer getStudentId() {
		return studentId;
	}
	public void setStudentId(Integer studentId) {
		this.studentId = studentId;
	}
	public String getStudentName() {
		return studentName;
	}
	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getStudentNo() {
		return studentNo;
	}
	public void setStudentNo(String studentNo) {
		this.studentNo = studentNo;
	}
	public Date getbirthDay() {
		return birthDay;
	}
	public void setbirthDay(Date birthDay) {
		this.birthDay = birthDay;
	}
	@Override
	public String toString() {
		return "User [studentId=" + studentId + ", studentName=" + studentName + ", age=" + age + ", studentNo="
				+ studentNo + ", birthDay=" + birthDay + "]";
	}
	
}

5)接口与映射文件:

mybatis实现原理及简单的增删改查

UserMapper.java:

package cn.xxs.mapper;

import java.util.List;

import cn.xxs.pojo.Student;

public interface UserMapper {
	/**
	 * 通过学生编号查询
	 * @param id
	 * @return
	 */
	public Student getStudentById(Integer studentId);
	/**
	 * 插入学生数据
	 * @param user
	 */
	public void addStudent(Student student);
	/**
	 * 修改学生数据
	 * @param user
	 */
	public void updateStudent(Student student);
	/**
	 * 根据id删除学生数据
	 * @param id
	 */	 
	public void delStudent(Integer student);	
	/**
	 * 根据学生姓名模糊查询学生信息
	 * @param studentName
	 * @return
	 */
	public List<Student> getStudentByName(String studentName);
}

映射文件UserMapper.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 命名  #{}:点位符,相当于jdbc的?-->
<mapper namespace="cn.xxs.mapper.UserMapper">
	<!-- id: sql中语句的唯一标识
	    parameterType :入参的数据类型
		resultType:返回结果的数据类型
	 -->
	 <!-- 通过学生编号查询 -->
	<select id="getStudentById" parameterType="int" resultType="student">
		select * from tblstudent where studentId = #{studentId}
	</select>
	<!-- 插入学生数据 -->
	<insert id="addStudent" parameterType="student">
		insert into tblstudent(studentId,studentName,age,studentNo,birthDay)
		values(#{studentId},#{studentName},#{age},#{studentNo},#{birthDay})
	</insert>
	<!-- 修改学生数据 -->
	<update id="updateStudent" parameterType="student">
		update tblstudent set studentName = #{studentName},
		age = #{age}
		where studentId = #{studentId}		
	</update>
	<!-- 根据id删除学生数据 -->
	<delete id="delStudent" parameterType="int">
		delete from tblstudent where studentId = #{studentId}
	</delete>
	<!-- 根据学生姓名模糊查询学生信息 -->
	<select id="getStudentByName" parameterType="String" resultType="student">
		 select * from tblstudent where studentName LIKE "%"#{studentName}"%"		 
		 <!-- select * from tblstudent where studentName LIKE concat(concat('%',#{studentName}),'%') -->		 
	</select>
</mapper>

6)工具类:

mybatis实现原理及简单的增删改查

package cn.xxs.util;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
/**
 * 获取SqlSessionFactory
 * @author xxs
 *
 */
public class SqlSessionFactoryUtil {

	private static SqlSessionFactory sqlSessionFactory;

	static {
	
		try {
			//声明resource
			String resource = "SqlMapConfig.xml";		
			//创建核心配置文件的输入流
			InputStream inputStream = Resources.getResourceAsStream(resource);		
			//通过输入流创建SqlSessionFactory
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 
		
	}
	
	public static SqlSessionFactory getSqlSessionFactory() {
		return sqlSessionFactory;
	}
	
}

7)测试类:

mybatis实现原理及简单的增删改查

package cn.xxs.test;

import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

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 cn.xxs.mapper.UserMapper;
import cn.xxs.pojo.Student;
import cn.xxs.util.SqlSessionFactoryUtil;

public class Test {
	/**
	 * 1、根据studentId查询学生信息,控制台输出
	 * @throws IOException 
	 */
	@org.junit.Test
	public void getStudentById() throws IOException {
		
		//通过输入流创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();		
		//创建SqlSession对象
		SqlSession ss = sqlSessionFactory.openSession();		
		//多态的运用,为掉方法做准备			
		UserMapper userMapper = ss.getMapper(UserMapper.class);	
		//根据studentId查询学生信息
		Student s = userMapper.getStudentById(1);
		//控制台输出
		System.out.println(s.toString());
		//释放资源
		ss.close();
	
	}
	/**
	 * 2.添加一条学生记录
	 * @throws IOException
	 */
	@org.junit.Test
	public void addStudent() throws IOException {
		
		//通过输入流创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();		
		//创建SqlSession对象
		SqlSession ss = sqlSessionFactory.openSession();		
		//多态的运用,为掉方法做准备			
		UserMapper userMapper = ss.getMapper(UserMapper.class);		
		Student s = new Student();
		//添加一条学生记录
		s.setStudentName("sxj");
		s.setAge(19);
		s.setStudentNo("0609170810");	
		//转换数据类型
		SimpleDateFormat sdf =new SimpleDateFormat("yyyy-mm-dd");		
		try {
			Date parse = sdf.parse("1997-10-20");
			s.setbirthDay(parse);
		} catch (ParseException e) {			
			e.printStackTrace();
		}
		//执行添加
		userMapper.addStudent(s);
		//提交事务
		ss.commit();
		//释放资源
		ss.close();
	
	}
	
	/**
	 * 3、根据id修改一条记录, 把原记录中的学生姓名和年龄进行修改,然后查询并在控制台输出。
	 * @throws IOException
	 */
	@org.junit.Test
	public void updateStudent() throws IOException {
		
		//通过输入流创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();		
		//创建SqlSession对象
		SqlSession ss = sqlSessionFactory.openSession();		
		//多态的运用,为掉方法做准备		
		UserMapper userMapper = ss.getMapper(UserMapper.class);		
		Student s = new Student();
		//根据id修改
		s.setStudentId(1);
		s.setStudentName("sxj");
		s.setAge(20);							
		userMapper.updateStudent(s);
		//提交事务
		ss.commit();
		//查询并在控制台输出
		getStudentById();
		System.out.println(s.toString());
		//释放资源
		ss.close();
	
	}
	
	/**
	 * 4、根据id删除一条记录。
	 * @throws IOException
	 */
	@org.junit.Test
	public void delStudent() throws IOException {		
		//通过输入流创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();		
		//创建SqlSession对象
		SqlSession ss = sqlSessionFactory.openSession();		
		//多态的运用,为掉方法做准备			
		UserMapper userMapper = ss.getMapper(UserMapper.class);	
		//执行删除
		userMapper.delStudent(2);
		//提交事务
		ss.commit();
		//释放资源
		ss.close();
	
	}
	
	/**
	 * 5、根据学生姓名模糊查询学生信息,并在控制台输出
	 * @throws IOException 
	 */
	@org.junit.Test
	public void getStudentByName() throws IOException {
		
		//通过输入流创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();		
		//创建SqlSession对象
		SqlSession ss = sqlSessionFactory.openSession();		
		//多态的运用,为掉方法做准备		
		UserMapper userMapper = ss.getMapper(UserMapper.class);	
		//根据学生姓名模糊查询学生信息
		List<Student> s = userMapper.getStudentByName("s");
		//并在控制台输出
		System.out.println(s.toString());
		//释放资源
		ss.close();
	
	}
}