最近工作比较忙一点,博客半个月没有更新了。之前一直想要完成一版Mybatis的源码分析。当我看完源码之后,却发现因为懒耽搁了整个过程,现在我们再来重头捋一下,Mybatis是干了什么,怎么干的。首先在本讲,我先介绍一下Mybatis的基础使用。这部分不废话多说,直接拉取的自己的Dem,只为了做一个展示。读者在看这一部分需要给自己一个思考。大家都在使用Mybatis作为数据库连接的一个框架,到底Mybatis做了什么呢?我们都配置了什么?而Mybatis读取我们的配置后是怎么在运行时得到我们想要的结果的呢?
零、传统JDBC的使用:
此段代码来自:http://blog.csdn.net/lhyzyp/article/details/72868910
首先,我们看一下JDBC帮我祝我们做了什么。
1. 加载驱动
2.连接数据库并获取数据库连接对象
3.执行sql
4.返回结果
5.关闭连接
package com.JDBCdemo;
import java.sql.*;
/**
*
* @author : pinsily
* @email : 13160724868@163.com
* @version : 0.0.1
* @create_time : 2017年6月5日 上午9:31:46
*
* @update_time : 2017年6月5日 下午16:26:22 增加 增删查改 功能,方便以后使用
*
*/
public class testJDBC {
/**
* 加载驱动
* */
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接
* */
public static Connection getConnection() {
String url = "jdbc:mysql://localhost:3306/student";
String username = "root";
String password = "pinsily";
Connection con = null;
try {
con = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
/**
* 关闭连接
* */
public static void close(ResultSet rs, Statement stm, Connection con) {
try {
if (rs != null)
rs.close();
if (stm != null) {
stm.close();
}
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 插入数据,用得使用可以把 sql语句 当成参数
* */
public void insert() {
String sql = "insert into student_table (name) values('pinsily')";
Connection con = getConnection();
Statement stm = null;
try {
stm = con.createStatement();
//执行 SQL 语句并返回结果
int result = stm.executeUpdate(sql);
if (result != 0) {
System.out.println("操作成功,受影响" + result + "行");
}
} catch (SQLException e) {
System.out.println("操作失败");
} finally {
close(null, stm, con);
}
}
/**
* 删除操作,用得使用可以把 sql语句 当成参数
* */
public void delete() {
String sql = "delete from student_table where name = 'pinsily'";
Connection con = getConnection();
Statement stm = null;
try {
stm = con.createStatement();
int count = stm.executeUpdate(sql);
System.out.println("删除 " + count + " 条数据\n");
} catch (SQLException e) {
System.out.println("删除数据失败");
}finally {
close(null, stm, con);
}
}
/**
* 查询数据库,用得使用可以把 sql语句 当成参数
* */
public void query() {
String sql = "select * from student_table";
Connection con = getConnection();
Statement stm = null;
ResultSet rs = null;
try {
stm = con.createStatement();
//执行sql查询语句,返回查询数据的结果集
rs = stm.executeQuery(sql);
System.out.println("查询结果为:");
// 判断是否还有下一个数据
while (rs.next()) {
// 根据字段名获取相应的值
String name = rs.getString("name");
int id = rs.getInt("id");
//输出查到的记录的各个字段的值
System.out.println(id+":"+name);
}
} catch (SQLException e) {
System.out.println("查询数据失败");
}finally {
close(rs, stm, con);
}
}
/**
* 更新操作,用得使用可以把 sql语句 当成参数
* */
public void update() {
String sql = "update student_table set name='zhuyuanpeng' where id = 3 ";
Connection con = getConnection();
Statement stm = null;
try {
//创建用于执行sql语句的Statement对象
stm = con.createStatement();
// 执行更新操作的sql语句,返回更新数据的个数
int count = stm.executeUpdate(sql);
//输出更新操作的处理结果
System.out.println("表中更新 " + count + " 条数据");
} catch (SQLException e) {
System.out.println("更新数据失败");
}finally {
close(null, stm, con);
}
}
/**
* 测试函数
* */
public static void main(String[] args) {
testJDBC j = new testJDBC();
//j.insert();
//j.delete();
//j.update();
j.query();
}
}
一、Mybatis的基本使用
Mybatis其实和基本的JDBC一样,只不过为了我们的使用方便,提供了更多的功能和人性化的配置。
首先让我们看看MyBatis如何QuickStart
1.1、新建一个mybatis-config.xml文件,对mybatis的基本信息进行配置。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1/lixinjiantest?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
<?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"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/usermapper.xml"/>
</mappers>
</configuration>
首先,我们使用了外部的读取配置文件的形式,避免了将url、pwd、uername、driver等信息写死在配置文件中。在我是个新手的时候,我并不能体会到将可配置的文件独立出来的好处。当工作了以后我发现,很多时候将多变的,该独立的,能独立的东西独立出来,可以大大节省您的时间。
其次我们配置了一个池化的数据源
最后我们配置了mapper来描述我们mapper.xml的位置。mapper.xml用来定义sql,和resultMap
<?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="baseDAO.mybatis.mapper.UserMapper">
<resultMap id="UserResultMap" type="baseDAO.mybatis.domain.User">
<id column="user_id" property="userId" />
<result column="user_name" property="userName" />
<result column="user_phone" property="userPhone" />
<result column="user_location" property="userLocation" />
</resultMap>
<select id="findAll" resultMap="UserResultMap">
select user_id,user_phone,user_location,user_name from USER
</select>
<select id="findOne" parameterType="Integer" resultMap="UserResultMap">
select user_id,user_phone,user_location,user_name from USER where user_id=#{id}
</select>
</mapper>
我们可以清晰的观察到,我们配置了namespace: 这个就是dao层的接口的位置。
resultMap便是你返回的结果和你Java实体类的映射。
再后来我们定义了以Dao层接口方法名同名的SQL语句。每一个Sql语句被定义为一个Statement
再然后,我们只需要定义自定义的DAO层Mapper和我们的实体类,再封装service我们就可以开心的使用Mybatis来完成对数据库的访问了。
package baseDAO.mybatis.mapper;
import java.io.IOException;
import java.util.List;
public interface BaseMapper<K,T> {
public List<T> findAll() throws IOException;
public List<T> findOne(K k) throws IOException;
}
package baseDAO.mybatis.mapper;
public interface UserMapper extends BaseMapper {
}
package baseDAO.mybatis.domain;
import lombok.Data;
@Data
public class User {
private Integer userId;
private Integer userPhone;
private String userName;
private String userLocation;
}
package baseDAO.mybatis.service;
import baseDAO.mybatis.domain.User;
import baseDAO.mybatis.mapper.UserMapper;
import org.apache.ibatis.session.SqlSession;
import baseDAO.mybatis.utils.SessionHelpUtils;
import java.io.IOException;
import java.util.List;
public class UserService {
public List<User> findAll() throws IOException {
SqlSession sqlSession = SessionHelpUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.findAll();
}
public List<User> findOne(Integer id) throws IOException {
SqlSession sqlSession = SessionHelpUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return (List<User>) mapper.findOne(id);
}
}
声明一个Util去获取Mybatis的入口对象:sqlSession
package baseDAO.mybatis.utils;
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 java.io.IOException;
public class SessionHelpUtils {
private static SqlSessionFactory sqlSessionFactory = null;
private static SqlSession sqlSession = null;
static {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
try {
sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("baseDAO_resources/mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() throws IOException {
if(sqlSessionFactory != null){
sqlSession = sqlSessionFactory.openSession();
}
return sqlSession;
}
}
Test/controller
package baseDAO.mybatis.service;
import baseDAO.mybatis.domain.User;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
public class UserServiceTest {
@Test
public void findAllTest(){
try {
new UserService().findAll().stream().forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void findOneTest(){
UserService userService = new UserService();
try {
List<User> one = userService.findOne(1405007);
System.out.println(one);
} catch (IOException e) {
e.printStackTrace();
}
}
}