MyBatis入门基础(一)

阅读目录

回到顶部

一:对原生态 JDBC 问题的总结

  新项目要使用 mybatis 作为持久层框架,由于本人之前一直使用的 Hibernate,对 mybatis 的用法实在欠缺,最近几天计划把 mybatis 学习一哈,特将学习笔记记录于此,方便大家参考,也方便自己查阅。

  话不多说,先看看原始的 JDBC 程序代码,看看这样的代码存在什么问题。

package com.utils;

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

/**

  • @ClassName: JdbcTest
  • @Description: TODO(原始的 JDBC 操作数据库)
  • @author warcaft
  • @date 2015-6-27 下午 3:31:22

*/
public class JdbcTest {
public static void main(String[] args) {

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 数据库连接</span>
    Connection connection = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 预编译的Statement,使用预编译的Statement提高数据库性能</span>
    PreparedStatement preparedStatement = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 结果 集</span>
    ResultSet resultSet = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 加载数据库驱动</span>
        Class.forName("com.mysql.jdbc.Driver"<span style="color: rgba(0, 0, 0, 1)">);

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通过驱动管理类获取数据库链接</span>
        connection =<span style="color: rgba(0, 0, 0, 1)"> DriverManager
                .getConnection(
                        </span>"jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"<span style="color: rgba(0, 0, 0, 1)">,
                        </span>"root", "root"<span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 定义sql语句 ?表示占位符</span>
        String sql = "select * from t_user where username = ?"<span style="color: rgba(0, 0, 0, 1)">;
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取预处理statement</span>
        preparedStatement =<span style="color: rgba(0, 0, 0, 1)"> connection.prepareStatement(sql);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值</span>
        preparedStatement.setString(1, "王五"<span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 向数据库发出sql执行查询,查询出结果集</span>
        resultSet =<span style="color: rgba(0, 0, 0, 1)"> preparedStatement.executeQuery();
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 遍历查询结果集</span>
        <span style="color: rgba(0, 0, 255, 1)">while</span><span style="color: rgba(0, 0, 0, 1)"> (resultSet.next()) {
            System.out.println(resultSet.getString(</span>"id") + "  "
                    + resultSet.getString("username"<span style="color: rgba(0, 0, 0, 1)">));
        }
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
        e.printStackTrace();
    } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 释放资源</span>
        <span style="color: rgba(0, 0, 255, 1)">if</span> (resultSet != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                resultSet.close();
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO Auto-generated catch block</span>

e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
}
catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

    }

}

}

View Code

上面代码的问题总结:

1、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。

解决方案:使用数据库连接池管理数据库连接。

2、将 sql 语句硬编码到 java 代码中,如果 sql 语句修改,需要重新编译 java 代码,不利于系统维护。

解决方案:将 sql 语句配置在 xml 配置文件中,即使 sql 变化,不需要对 java 代码进行重新编译。

3、向 preparedStatement 中设置参数,对占位符号位置和设置参数值,硬编码在 java 代码中,不利于系统维护。

解决方案:将 sql 语句及占位符号和参数全部配置在 xml 中。

4、从 resutSet 中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,,不利于系统维护。

解决方案:将查询的结果集,自动映射成 java 对象。

回到顶部

二:MyBatis 框架

  1.MyBatis 是什么?(下载地址:https://github.com/mybatis/mybatis-3/releases) 

   MyBatis 本是apache的一个开源项目iBatis, 2010 年这个项目由 apache software foundation 迁移到了 google code,并且改名为 MyBatis,实质上 Mybatis 对 ibatis 进行一些改进。 

  MyBatis 是一个优秀的持久层框架,它对 jdbc 的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建 connection、创建 statement、手动设置参数、结果集检索等 jdbc 繁杂的过程代码。

  Mybatis 通过 xml 或注解的方式将要执行的各种 statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过 java 对象和 statement 中的 sql 进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射成 java 对象并返回。

  2.MyBatis 架构图

  

1、mybatis 配置

SqlMapConfig.xml,此文件作为 mybatis 的全局配置文件,配置了 mybatis 的运行环境等信息。

mapper.xml 文件即 sql 映射文件,文件中配置了操作数据库的 sql 语句。此文件需要在 SqlMapConfig.xml 中加载。

 2、通过 mybatis 环境等配置信息构造 SqlSessionFactory 即会话工厂

 3、由会话工厂创建 sqlSession 即会话,操作数据库需要通过 sqlSession 进行。

 4、mybatis 底层自定义了 Executor 执行器接口操作数据库,Executor 接口有两个实现,一个是基本执行器、一个是缓存执行器。

 5、Mapped Statement 也是 mybatis 一个底层封装对象,它包装了 mybatis 配置信息及 sql 映射信息等。mapper.xml 文件中一个 sql 对应一个 Mapped Statement 对象,sql 的 id 即是 Mapped statement 的 id。

 6、Mapped Statement 对 sql 执行输入参数进行定义,包括 HashMap、基本类型、pojo,Executor 通过 Mapped Statement 在执行 sql 前将输入的 java 对象映射至 sql 中,输入参数映射就是 jdbc 编程中对 preparedStatement 设置参数。

 7、Mapped Statement 对 sql 执行输出结果进行定义,包括 HashMap、基本类型、pojo,Executor 通过 Mapped Statement 在执行 sql 后将输出结果映射至 java 对象中,输出结果映射过程相当于 jdbc 编程中对结果的解析处理过程。

回到顶部

三:mybatis 入门程序

1. 需求:(1). 根据用户id(主键)查询用户信息 (2). 根据用户名称模糊查询用户信息 (3). 添加用户 4). 删除用户 (5). 更新用户

2. 环境:java 环境:JDK1.7,eclipse,Mysql5.1

3. 工程目录结构

 

4. 从 mybatis 的 jar 包结构可知 mybatis 用的是 log4j 记录日志,所以 log4j.properties 文件内容如下:

# Global logging configuration
#在开发的环境下,日志级别要设置成 DEBUG,生产环境设置成 info 或 error
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

5.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>
    <!-- 和 spring 整合后 environments 配置将废除-->
    <environments default="development">
        <environment id="development">
        <!-- 使用 jdbc 事务管理, 事务控制由 mybatis 管理-->
            <transactionManager type="JDBC" />
        <!-- 数据库连接池, 由 mybatis 管理-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
<!-- 加载映射文件 -->
    <mappers>
        <mapper resource="sqlmap/User.xml"/>
    </mappers>
</configuration>

6. 实体 User.java 内容

package com.mybatis.entity;

import java.util.Date;

/**

  • @ClassName: User
  • @Description: TODO(用户实体)
  • @author warcaft
  • @date 2015-6-27 下午 1:56:02

*/
public class User {
// 属性名称和数据库字段名称保持一致
private Integer id;
// 姓名
private String username;
// 性别
private String sex;
// 地址
private String address;
// 生日
private Date birthday;

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Integer getId() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> id;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setId(Integer id) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.id =<span style="color: rgba(0, 0, 0, 1)"> id;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getUsername() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> username;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setUsername(String username) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username =<span style="color: rgba(0, 0, 0, 1)"> username;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getSex() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sex;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setSex(String sex) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.sex =<span style="color: rgba(0, 0, 0, 1)"> sex;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getAddress() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> address;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setAddress(String address) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.address =<span style="color: rgba(0, 0, 0, 1)"> address;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Date getBirthday() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> birthday;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setBirthday(Date birthday) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.birthday =<span style="color: rgba(0, 0, 0, 1)"> birthday;
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String toString() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "User [id=" + id + ", username=" + username + ", sex=" +<span style="color: rgba(0, 0, 0, 1)"> sex
            </span>+ ", address=" + address + ", birthday=" + birthday + "]"<span style="color: rgba(0, 0, 0, 1)">;
}

}

View Code

7. 映射文件 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">
<!-- namespace 命名空间, 作用就是对 sql 进行分类化的管理, 理解为 sql 隔离
    注意: 使用 mapper 代理开发时,namespace 有特殊作用
 -->
<mapper namespace="test">
<!-- 在映射文件中配置很多 sql 语句 -->
<!-- 需求:通过 Id 查询用户表的记录 -->
<!-- 通过 SELECT 执行数据库查询 
    id: 标识映射文件中的 sql,称为 statement 的 id;
        将 sql 语句封装在 mapperStatement 的对象中,所以 Id 称为 Statement 的 id;
    parameterType: 指定输入参数的类型, 这里指定 int 型
    #{}: 表示一个占位符;
    #{id}: 其中 Id 表示接收输入的参数,参数名称就是 Id, 如果输入参数是简单类型,#{} 中的参数名可以任意,可以是 value 或者其它名称;
    resultType: 指定 sql 输出结果所映射的 java 对象类型,select 指定 resultType 表示将单条记录映射成 java 对象。
-->
<select id="findUserById" parameterType="int" resultType="com.mybatis.entity.User" >
    select * from t_user where id=#{id}
</select>
<!-- 根据用户名称模糊查询用户信息, 可能返回多条数据
    resultType: 指定的就是单条记录所映射的 java 类型;
    ${}: 表示拼接 sql 字符串,将接收到的参数内容不加任何修饰拼接在 sql 中.
    使用 ${} 拼接 sql,可能会引起 sql 注入
    ${value}: 接收输入参数的内容,如果传入的是简单类型,${} 中只能使用 value
 -->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.mybatis.entity.User" >
    select * from t_user where username LIKE '%${value}%'
</select>
<!-- 添加用户 
parameterType: 指定输入的参数类型是 pojo(包括用户信息);
#{} 中指定 pojo 的属性名称,接收到 pojo 对象的属性值    ,mybatis 通过 OGNL( 类似 struts2 的 OGNL) 获取对象的属性值
-->
<insert id="insertUser" parameterType="com.mybatis.entity.User" >
    <!-- 
        将 insert 插入的数据的主键返回到 User 对象中;
        select last_insert_id(): 得到刚 insert 进去记录的主键值,只适用于自增主键;
        keyProperty: 将查询到的主键值,设置到 parameterType 指定的对象的那个属性
        order:select last_insert_id() 执行顺序,相对于 insert 语句来说它的执行顺序。
        resultType: 指定 select last_insert_id() 的结果类型;
     -->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        select last_insert_id()
    </selectKey>
    <!-- 
        使用 mysql 的 uuid(),实现非自增主键的返回。
        执行过程: 通过 uuid() 得到主键,将主键设置到 user 对象的 Id 的属性中,其次,在 insert 执行时,从 user 对象中取出 Id 属性值;
     <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
        select uuid()
    </selectKey>
        insert into t_user (id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
     -->
    insert into t_user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 删除用户 
    根据 ID 删除用户, 需要输入 Id 值
-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from t_user where id=#{id}
    </delete>
<!-- 更新用户 
    需要传入用户的 Id 和用户的更新信息
    parameterType: 指定 User 对象,包括 Id 和用户的更新信息, 注意:Id 是必须存在的
    #{id}: 从输入的 User 对象中获取 Id 的属性值
-->
<update id="updateUser" parameterType="com.mybatis.entity.User">
    update t_user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} 
    where id=#{id}
</update>

</mapper>

8. 测试程序 MybatisService.java 代码

package com.mybatis.service;

import java.io.IOException;
import java.io.InputStream;
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 org.junit.Test;

import com.mybatis.entity.User;

/**

  • @ClassName: MybatisService
  • @Description: TODO(mybatis 入门程序)
  • @author warcaft
  • @date 2015-6-27 下午 4:49:49

*/
public class MybatisService {
// 根据 Id 查询用户信息,得到一条记录结果
@Test
public void findUserByIdTest() {
// mybatis 的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream
= null;
SqlSession sqlSession
= null;
try {
inputStream
= Resources.getResourceAsStream(resource);
// 1. 创建会话工场, 传入 mybatis 的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2.通过工厂得到SqlSession</span>
        sqlSession =<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3.通过sqlSession操作数据库
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> selectOne:查询一条结果</span>
        User user = sqlSession.selectOne("test.findUserById", 1<span style="color: rgba(0, 0, 0, 1)">);
        System.out.println(user.toString());

    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e) {
        e.printStackTrace();
    } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (sqlSession != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            sqlSession.close();
        }
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (inputStream != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                inputStream.close();
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 根据姓名模糊查询用户信息,得到一条或多条记录结果</span>

@Test
public void findUserByNameTest() {
// mybatis 的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream
= null;
SqlSession sqlSession
= null;
try {
inputStream
= Resources.getResourceAsStream(resource);
// 1. 创建会话工场, 传入 mybatis 的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2.通过工厂得到SqlSession</span>
        sqlSession =<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3.通过sqlSession操作数据库
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> list中的user和resultType类型一致</span>
        List&lt;User&gt; list = sqlSession.selectList("test.findUserByName", "小"<span style="color: rgba(0, 0, 0, 1)">);
        System.out.println(list);

    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e) {
        e.printStackTrace();
    } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (sqlSession != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            sqlSession.close();
        }
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (inputStream != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                inputStream.close();
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 添加用户</span>

@Test
public void insertUserTest() {
// mybatis 的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream
= null;
SqlSession sqlSession
= null;
try {
inputStream
= Resources.getResourceAsStream(resource);
// 1. 创建会话工场, 传入 mybatis 的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 2. 通过工厂得到 SqlSession
sqlSession = sqlSessionFactory.openSession();
//插入用户的对象
User user = new User();
user.setUsername(
"小红");
user.setBirthday(
new Date());
user.setSex(
"1");
user.setAddress(
"上海");
// 3. 通过 sqlSession 操作数据库
// 第一个参数:映射文件中的 statement 的 Id, 等于 namespace + "." + statement 的 id;
// 第二个参数: 指定和映射文件中所匹配的 parameterType 类型的参数;
// sqlSession.selectOne 结果是与映射文件所匹配的 resultType 类型的对象;
sqlSession.insert("test.insertUser", user);
//执行提交事务
sqlSession.commit();

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">项目中经常需要 获取新增的用户的主键</span>

System.out.println(user.getId());

    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e) {
        e.printStackTrace();
    } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (sqlSession != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            sqlSession.close();
        }
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (inputStream != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                inputStream.close();
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 根据Id删除用户</span>

@Test
public void deleteUserTest() {
// mybatis 的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream
= null;
SqlSession sqlSession
= null;
try {
inputStream
= Resources.getResourceAsStream(resource);
// 1. 创建会话工场, 传入 mybatis 的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 2. 通过工厂得到 SqlSession
sqlSession = sqlSessionFactory.openSession();
// 3. 通过 sqlSession 操作数据库
// 第一个参数:映射文件中的 statement 的 Id, 等于 namespace + "." + statement 的 id;
// 第二个参数: 指定和映射文件中所匹配的 parameterType 类型的参数;
// sqlSession.selectOne 结果是与映射文件所匹配的 resultType 类型的对象;
//传入 Id,删除用户
sqlSession.delete("test.deleteUser", 7);
//执行提交事务
sqlSession.commit();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (sqlSession != null) {
sqlSession.close();
}
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 根据Id更新用户信息</span>

@Test
public void updateUserTest() {
// mybatis 的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream
= null;
SqlSession sqlSession
= null;
try {
inputStream
= Resources.getResourceAsStream(resource);
// 1. 创建会话工场, 传入 mybatis 的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 2. 通过工厂得到 SqlSession
sqlSession = sqlSessionFactory.openSession();
//更新用户的信息
User user = new User();
user.setId(
2);
user.setUsername(
"小黑");
user.setBirthday(
new Date());
user.setSex(
"2");
user.setAddress(
"上海");
// 3. 通过 sqlSession 操作数据库
// 第一个参数:映射文件中的 statement 的 Id, 等于 namespace + "." + statement 的 id;
// 第二个参数: 指定和映射文件中所匹配的 parameterType 类型的参数;
// sqlSession.selectOne 结果是与映射文件所匹配的 resultType 类型的对象;
//更具 Id 更新用户
sqlSession.update("test.updateUser", user);
//执行提交事务
sqlSession.commit();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (sqlSession != null) {
sqlSession.close();
}
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

9. 数据库所用 sql 脚本

CREATE TABLE t_user (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(30) NOT NULL COMMENT '用户名称',
  birthday DATE DEFAULT NULL COMMENT '生日',
  sex CHAR(2) DEFAULT NULL COMMENT '性别',
  address VARCHAR(256) DEFAULT NULL COMMENT '地址'
);
INSERT INTO t_user (username,birthday,sex,address)
                                VALUES
                   ('小 A','2015-06-27','2','北京'),
                   ('小 B','2015-06-27','2','北京'),
                   ('小 C','2015-06-27','1','北京'),
                   ('小 D','2015-06-27','2','北京');
回到顶部

四:mybatis 和 Hibernate 的本质区别与应用场景

hibernate:是一个标准ORM框架(对象关系映射),入门门槛较高的,不需要程序写sqlsql语句自动生成了,对 sql 语句进行优化、修改比较困难的。

应用场景:

     适用与需求变化不多的中小型项目,比如:后台管理系统,erpormoa。。

mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sqlmybatis 也可以实现映射(输入映射、输出映射)。

应用场景:

     适用与需求变化较多的项目,比如:互联网项目。

回到顶部

五:小结

1.parameterType 和 resultType

  parameterType: 在映射文件中通过 parameterType 指定输入 参数的类型。

  resultType: 在映射文件中通过 resultType 指定输出结果的类型

 2.#{} 和 ${}

#{} 表示一个占位符号,#{} 接收输入参数,类型可以是简单类型,pojo、hashmap;

如果接收简单类型,#{} 中可以写成 value 或其它名称;

#{} 接收 pojo 对象值,通过 OGNL 读取对象中的属性值,通过属性. 属性. 属性... 的方式获取对象属性值。

 

${} 表示一个拼接符号,会引用 sql 注入,所以不建议使用 ${};

${} 接收输入参数,类型可以是简单类型,pojo、hashmap;

如果接收简单类型,${} 中只能写成 value;

${} 接收 pojo 对象值,通过 OGNL 读取对象中的属性值,通过属性. 属性. 属性... 的方式获取对象属性值。

3.selectOne()和 selectList()

  selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。

  selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne

  如果使用selectOne报错: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4