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 |
|
- 根据studentId查询学生信息,控制台输出
- 添加一条学生记录
- 根据id修改一条记录, 把原记录中的学生姓名和年龄进行修改,然后查询并在控制台输出。
- 根据id删除一条记录。
- 根据学生姓名模糊查询学生信息,并在控制台输出
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)项目结构:
3)配置文件:
数据库链接资源文件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)实体类:
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)接口与映射文件:
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)工具类:
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)测试类:
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();
}
}