沉迷于黑与白世界中的人,无论怎么挣扎,都逃不过被同化的命运。前世看见了什么,那么今世便是什么。

上一章简单介绍了S2SH框架整合开发版(十一),如果没有看过,​​请观看上一章​​。

一. JDBC 形式的缺点

MyBatis 是数据持久层的操作,是对数据库的处理, 在介绍它之前,先来了解一下,原来的jdbc 的处理,有哪些缺点,然后看看MyBatis 是如何进行改变的。
先来简单写一个User 类,只有id,name,age,sex,description 五个简单的字段,是简单的pojo 类。 对其进行简单的查询操作:

一.二 JDBC类

package com.yjl.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
@author:yuejl
@date: 2019年6月15日 上午11:53:34
@Description 类的相关描述
*/
public class DBUtils {
public static Connection getConnection(){
Connection connection=null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8",
"root","abc123");
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return connection;
}
public static void close(ResultSet resultSet,Statement statement,Connection connection){
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}

一.三 根据id 编号进行查询的方法

@Test
public void oldTest() throws SQLException{
Connection connection=DBUtils.getConnection();
String sql="select * from user where id=?";
PreparedStatement statement=connection.prepareStatement(sql);
statement.setInt(1, 1);
ResultSet resultSet=statement.executeQuery();
User user=null;
while(resultSet.next()){
user=new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getString("name"));
user.setAge(resultSet.getInt("age"));
user.setSex(resultSet.getString("sex"));
user.setDescription(resultSet.getString("description"));
}
DBUtils.close(resultSet,statement,connection);
System.out.println(user);
}

运行之后,会显示:

MyBatis的简单了解(一)_java


仔细观察,会发现这种写法,有很多的不足之处。

一.四 原始JDBC 开发的不足

  1. 数据库的连接。 数据库在使用时被创建,不使用就释放, 对数据库进行频繁的连接开启和关闭,造成数据库资源浪费,影响数据库的性能。
  2. 数据库信息被硬编码。
connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8", 
"root","abc123");

数据库的连接信息被硬编码到连接数据库类中,如果更换数据库,则需要改变相应的信息,重新编码。即使可以写在 jdbc.properties 等配置文件里面,那么还需要写一个单独的读取 jdbc.properties 文件信息的类。

  1. sql 语句被硬编码
String sql="select * from user where id=?";

如果sql 被修改, 实际开发中,是常常被修改的, 那么就必须重新编译,不利用系统维护。

  1. 向PreparedStatement 设置值时,对参数的位置 和值,硬编码到程序里面。 不利于系统维护。 如 设置 ? 时,id 放在了第一位, 如果有name, name放在了第二位, 那么在传参的时候,必须把id 放在第一个,name 放在第二个。
statement.setInt(1, 1);
  1. 遍历结果集数据时, 将获取表的字段值,进行了硬编码。不利用系统维护。
user=new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getString("name"));
user.setAge(resultSet.getInt("age"));
user.setSex(resultSet.getString("sex"));
user.setDescription(resultSet.getString("description"));

如,如果修改了数据库的字段,description, 现在要改成desc, 那么就都得改变,列名硬编码到程序中。 当然,可以通过 getInt(1),getString(2) 这样的索引顺序来取得,那么列名就不硬编码了,但是 索引顺序就硬编码了。 改变sql 前后值的顺序,就有可能出错。

  1. 某些功能无法实现。
    如 根据传过来的值,来动态的显示列。 即 前台传入列的名称,来动态的显示 列。 前台传入name 和sex, 就查询name 和sex 列, 前台传入name,sex,age 就动态查询name,sex,age 列。

二. MyBatis

二.一 MyBatis 的出现

在MyBatis 之前,是叫 ibatis, 是Apache 组织的开发的。 现在交由github 管理了。 还有一种 持久化ORM ,叫Hibernate. 前面讲过。 可以看:
​Hibernate开发环境的简单搭建及常见错误(一)​​ 将Hibernate 与 MyBatis 进行比较性 开发。

MyBatis 的下载网址是:

​https://github.com/mybatis/mybatis-3​

MyBatis的简单了解(一)_java_02


下载之后:

MyBatis的简单了解(一)_java_03


其中, mybatis-3.4.5.jar 是开发的jar 包, mybatis-3.4.5.pdf 是帮助文档, lib 是常用的关联jar 包。

MyBatis的简单了解(一)_java_04

二.二 MyBatis 的作用

mybatis是一个持久层的框架,是apache下的顶级项目。
mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。
mybatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)

三. MyBatis 的简单开发

通过Mybatis, 对user 表进行查询,按照id 进行查询和 查询全部。

其中,数据库表 user 为: 两条数据。

MyBatis的简单了解(一)_MyBatis的简单例子_05


创建简单的Java 项目即可,暂时先不用创建Web项目。

三.一 导入jar包

需要导入 mybatis 的jar包, mybatis 的关联包, 和mysql驱动 的jar包。

MyBatis的简单了解(一)_apache_06

三.二 创建User.java 简单类

package com.yjl.pojo;
/**
@author:yuejl
@date: 2019年6月15日 上午11:11:02
@Description Mybatis 使用的基本类 User
*/
public class User {
/**
* @param id id编号,自增
* @param name 姓名
* @param age 年龄
* @param sex 性别
* @param description 描述
*/
private Integer id;
private String name;
private Integer age;
private String sex;
private String description;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", description=" + description
+ "]";
}
}

三.三 创建UserDao 接口和UserDaoImpl 实现类

UserDao 接口:

package com.yjl.dao;

import java.util.List;

import com.yjl.pojo.User;

/**
@author:yuejl
@date: 2019年6月15日 上午11:26:23
@Description 类的相关描述
*/
public interface UserDao {
User getById(int id);
List<User> findAll();
}

UserDaoImpl 实现类:

package com.yjl.dao.impl;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.yjl.dao.UserDao;
import com.yjl.pojo.User;
import com.yjl.util.SqlSessionFactoryUtils;

/**
@author:yuejl
@date: 2019年6月15日 上午11:26:36
@Description 类的相关描述
*/
public class UserDaoImpl implements UserDao{

@Override
public User getById(int id) {
return null;
}

@Override
public List<User> findAll() {
return null;
}

}

三.四 创建测试类

package com.yjl.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.junit.Test;

import com.yjl.dao.UserDao;
import com.yjl.dao.impl.UserDaoImpl;
import com.yjl.pojo.User;
import com.yjl.util.DBUtils;

/**
@author:yuejl
@date: 2019年6月15日 上午11:14:56
@Description 类的相关描述
*/
public class UserTest {
@Test
public void getByIdTest(){
UserDao userDao=new UserDaoImpl();
User user=userDao.getById(1);
System.out.println(user);
}
@Test
public void findAllTest(){
UserDao userDao=new UserDaoImpl();
List<User> allList=userDao.findAll();
allList.forEach(n ->System.out.println(n));
}
}

三.五 MyBatis 的核心配置文件 SqlMapConfig.xml

在src 目录下,创建 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>
<!-- 开发环境 development -->
<environments default="development">
<environment id="development">
<!-- 事务管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 ,为pooled 连接池 -->
<dataSource type="pooled">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="abc123"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 引入文件资源 -->
<mapper resource="com/yjl/pojo/User.xml"/>
</mappers>
</configuration>

三.六 MyBatis 的工具类 SqlSessionFactoryUtils ,用于获取SqlSession

package com.yjl.util;

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

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
@author:两个蝴蝶飞
@date: 2019年6月15日 上午11:13:26
@Description 类的相关描述
*/
public class SqlSessionFactoryUtils {
/*创建SqlSession的工厂 SqlSessionFactory对象*/
private static SqlSessionFactory sqlSessionFactory=null;
private SqlSessionFactoryUtils(){

}
/**
* 单例模式 获取实例
* @author 两个蝴蝶飞
* @return
*/
public static SqlSessionFactory getInstance(){
synchronized(SqlSessionFactoryUtils.class){
if(sqlSessionFactory==null){
InputStream input=null;
// Mybatis 核心配置文件名
String resource_name="SqlMapConfig.xml";
try {
input=Resources.getResourceAsStream(resource_name);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(input);
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sqlSessionFactory;
}
/**
*
* @author 两个蝴蝶飞
* @return 获取当前的Session
*/
public static SqlSession getSession(){
if(sqlSessionFactory==null){
getInstance();
}
return sqlSessionFactory.openSession();
}
}

三.七 MyBatis 的实体配置文件 User.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.yjl.pojo.User">
<select id="getById" parameterType="int" resultType="com.yjl.pojo.User">
<!--正常的sql 语句。 -->
select * from user where id=#{id}
</select>
<select id="findAll" resultType="com.yjl.pojo.User">
select * from user
</select>
</mapper>

三.八 引入log4j.properties 日志文件

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
## 配置mybatis 的日志级别为debug
log4j.logger.org.mybatis=debug
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout

配置完成后的,目录结构如下:

MyBatis的简单了解(一)_sql_07

三.九 UserDaoImpl 类的 getById() 方法实现

@Override
public User getById(int id) {
//调用selectOne 方法,进行查询。 第一个传入的是id 值,为User.xml 的 namespace+id 的值。
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
User user=null;
try{
user=sqlSession.selectOne("com.yjl.pojo.User.getById",userId);
}finally{
sqlSession.close();
}
return user;
}

三.十 UserDaoImpl 类的findAll() 方法实现

@Override
public List<User> findAll() {
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
List<User> allList=new ArrayList<User>();
try{
allList=sqlSession.selectList("com.yjl.pojo.User.findAll");
}finally{
sqlSession.close();
}

return allList;
}

四. 测试方法

四.一 测试getById() 方法

观察log4j 日志输出。

MyBatis的简单了解(一)_sql_08

  1. 打开jdbc 连接
  2. 创建连接
  3. 设置自动提交 为false.
  4. 查询sql 语句
  5. 传参数 1
  6. 查询记录,为1 条。

四.二 测试findAll() 方法

MyBatis的简单了解(一)_MyBatis的简单例子_09

谢谢!!!