什么是MyBatis?
MyBatis的前身是iBATIS,是一个开源项目,最初侧重与密码软件的开发,后来发展为基于Java的持久层框架。MyBatis是一款优秀的支持自定义SQL查询,存储过程和高级映射的持久层框架,消除了几乎所有的JDBC代码和参数的手动设置以及结果集的搜索,MyBatis可以使用XML或注解进行配置和映射,MyBatis通过将参数映射到配置的SQL形成最终执行的SQL语句,最后将执行SQL的结果映射成Java对象返回。
与MyBatis相比较,JDBC明显存在一些缺点:数据库连接使用时使用完成后关闭,不使用释放,频繁开启和关闭数据库影响数据库性能(解决:连接池,本质在于连接复用);不同需求需要将Java代码进行改变,每次改变需要重新编译,不利于系统维护(解决:将SQL语句与Java代码分离(SQL语句与配置在XML文件中),需求改变不需要修改Java代码);根据结果集ResultSet遍历数据,存在硬编码,不利于系统维护(解决:将查询结果映射为Java对象)
Mybatis基本编程流程
本例是使用XML形式进行配置的,
1、导包(数据库和依赖)
<!--mysql连接数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<!--mybatis的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!--log4j日志依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2、全局配置文件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>
<!--加载数据库的连接参数的配置文件-->
<!--<properties resource="jdbc.properties"/>-->
<!--配置运行的环境 (在Spring中不在使用)-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
注:
- <setting>中的logImpl属性配置指定使用LOG4J输出日志
- <typeAliases>元素下面配置了一个包的别名,通常确定一个类的时候需要使用类的全限定名称,例如:com.mybatis.model.Country,在MyBatis中需要频繁用到类的全限定名称,为了方便使用,配置了com.mybatis.model包,配置后,在使用类的时候不需要写包的部分,只使用Country即可。
- <enviroments>环境配置中主要配置了数据库连接,数据库的url 为jdbc:mysql://localhost:3306/test,使用的是本机的test数据库,后面的username 和password分别是数据库的用户名和密码。
- <mappers>中配置了一个包含完整类路径的Mapper.xml,这是一个MyBatis的SQL语句和映射配置文件。
3、对应的接口文件,实体类、xml文件、
-bean
--Student类(实体类)
public class Student {
private int SID;
private String Sname;
private double Score;
public int getSID() {
return SID;
}
public void setSID(int SID) {
this.SID = SID;
}
public String getSname() {
return Sname;
}
public void setSname(String sname) {
Sname = sname;
}
public double getScore() {
return Score;
}
public void setScore(double score) {
Score = score;
}
@Override
public String toString() {
return "Student{" +
"SID=" + SID +
", Sname='" + Sname + '\'' +
", Score=" + Score +
'}';
}
}
对应的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">
<!-- namespace命名空间特殊作用: 如果使用mapper动态代理方法,这里就需要配置mapper接口地址-->
<mapper namespace="com.tulun.dao.StudentMapper">
<select id="selectStudentByPK" parameterType="int" resultType="com.tulun.bean.Student">
select * from Student where SID=#{id}
</select>
</mapper>
对应的mapper.java的接口文件
public interface StudentMapper {
/**
* 通过主键查询数据实体
* @param sid
* @return
*/
public Student selectStudentByPK(int sid);
}
注:
SQL定义在对一个的xml文件中,里面的配置作用如下:
- <mapper> :XML的根元素,属性namespace定义了当前XML的命名空间
- <select>元素:定义了一个SELECT查询
- id属性:定义了当前SELECT查询的唯一一个id,一般是接口中对应的方法名
- resultType:定义当前查询的返回值类型,若在全局配置文件中未设置别名,此处需要写成返回类的全限定名称
创建好实体和对应的xml文件后,接下来要有针对性地配置Log4j,使MybBatis在执行数据库操作时可以将执行的SQL与其他信息输出到控制台。
## debug 级别
log4j.rootLogger=DEBUG,Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{yyyy-MM-dd-HH\:mm\:ss,SSS} [%t] [%c] [%p] - %m%n
log4j.logger.com.mybatis=DEBUG /
##输出sql 语句
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG</strong>
4、在全局的配置文件上添加mapper的映射
<mappers>
<!-- resource方式在UserMapper.xml,定义namespace为mapper接口的地址,映射文件通过namespace找到对应的mapper接口文件-->
<mapper resource="mapper/StudentMapper.xml"/>
<!-- class方式class:指定 mapper接口的地址遵循规则:将mapper.xml和mapper.java文件放在一个目录 且文件名相同-->
<!-- <mapper class="cn.itcast.mybatis.mapper.UserMapper"/> -->
<!--批量mapper扫描遵循规则:将mapper.xml和mapper.java文件放在一个目录 且文件名相同-->
<!--<package name="com.etc.mapper"/>-->
</mappers>
5、查询过程:
public static void main(String[] args) throws IOException {
//mybatis配置文件名
String resource = "mybatis-config.xml";
//通过mybatis提供的Resources类来读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过SqlSessionFactoryBuilder类创建一个SqlSessionFactory工厂实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过sqlsessionFactory实例创建sqlsession实例
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过反射机制来获取对应mapper实例
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//调用mapper实例下方法
Student student = mapper.selectStudentByPK(1);
System.out.println(student);
}
或创建测试类进行测试
package MavenLG.mapper;
import MavenLG.bean.Student;
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 org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class TestStudentMapper {
static SqlSessionFactory sqlSessionFactory = null;
@Before
public void setUp() throws IOException {
//mybatis配置文件名
String resource = "mybatis-config.xml";
//通过mybatis提供的Resources类来读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过SqlSessionFactoryBuilder类创建一个SqlSessionFactory工厂实例
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testGetStudentById(){
//通过sqlsessionFactory实例创建sqlsession实例
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过反射机制来获取对应mapper实例
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//调用mapper实例下方法
Student student = mapper.getStudentById(1);
System.out.println(student);
sqlSession.close();
}
@Test
public void testInsertStudent(){
//通过sqlsessionFactory实例创建sqlsession实例
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过反射机制来获取对应mapper实例
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//调用mapper实例下方法
Student student1 = new Student();
student1.setSID(5);
student1.setSname("lisi");
student1.setScore(97.3);
mapper.insertStudent(student1);
sqlSession.commit();
sqlSession.close();
}
}
注:
- 通过Resource工具类将全局配置文件读入Reader
- 再通过SqlSessionFactoryBuilder建造类使用Reader创建SqlSessionFactory对象工厂对象,在创建SqlSessionFactory对象的过程中,首先解析全局配置文件,读取配置文件中的mappers配置后会读取全部的Mapper.xml进行具体方法解析,解析完成后,SqlSessionFactory就包含了所有属性配置和执行SQL的信息
- 使用时通过SqlSessionFactory工厂对象获取一个SqlSession
- 通过SqlSession的selectList方法查找到对应mapper.xml中id对应的方法,执行SQL查询
- MyBatis底层使用JDBC执行SQL,获得结果集ResultSet后,根据resultType的配置将结果映射为其返回类型的集合,返回查询对象
- 当进行插入或删除等操作时,由于默认修改结果手动提交,故调用SqlSession的commit方法进行结果提交,或将其改为自动提交
- 注意,最后要关闭SqlSession,否则会因为连接没有关闭导致数据库连接数过多,造成系统崩溃
配置完成,会输出如下日志:
2019-06-10-21:35:17,873 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Created connection 10443789.
2019-06-10-21:35:17,874 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@9f5c0d]
2019-06-10-21:35:17,876 [main] [MavenLG.mapper.StudentMapper.getStudentById] [DEBUG] - ==> Preparing: select * from student where SID=?
2019-06-10-21:35:17,911 [main] [MavenLG.mapper.StudentMapper.getStudentById] [DEBUG] - ==> Parameters: 1(Integer)
2019-06-10-21:35:21,262 [main] [MavenLG.mapper.StudentMapper.getStudentById] [DEBUG] - <== Total: 1
Student{SID=1, Sname='zhang', Score=60.5}