Mybatis框架学习(一)

Mybatis简介

       MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。

       Mybatis是面向sql的持久层框架,封装了jdbc访问数据库的过程,开发过程,只需专注于sql语句本身的拼装,其它复杂的过程全部可以交给mybatis去完成。

        目前最主流的持久层框架为hibernate与mybatis,而且国内目前情况使用Mybatis的公司比hibernate要多  

        Hibernate学习门槛不低,要精通门槛更高。门槛高在怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate缓存与数据加载策略方面需要经验和能力都很强才行。

        sql优化方面,Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。

JDBC存在问题

       频繁创建和打开、关闭数据库连接,太消耗资源

       Sql语句存在硬编码,不利于维护

       Sql参数设置硬编码,不利于维护

       结果集获取与遍历复杂,存在硬编码,不利于维护,期望能够查询后返回一个java对象

初始案例    

       创建数据库

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `orders`
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '下单用户id',
  `number` varchar(32) NOT NULL COMMENT '订单号',
  `createtime` datetime NOT NULL COMMENT '创建订单时间',
  `note` varchar(100) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_order_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of orders
-- ----------------------------
INSERT INTO `order` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO `order` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO `order` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('26', '王五', null, null, null);

       导入依赖jar包

 

        创建 pojo对象

        

 

        配置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事务管理 -->
         <transactionManager type="JDBC" />
         <!-- 数据库连接池 -->
         <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="1234" />
         </dataSource>
      </environment>
   </environments>

   <!--加载映射文件-->
   <mappers>
      <mapper resource="user.xml"/>
   </mappers>

</configuration>

       配置log4j.properties

# Global logging configuration
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

      配置sql查询的映射文件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语句 -->
<mapper namespace="user">
    <!--
    id为sql语句唯一标识
    parameterType输入参数类型
    resultType输出结果类型
    #{}表示输入参数的占位符
    ${}字符串拼接指令 大括号内部为value作为输入参数
    -->
    <select id="getUserById" parameterType="int" resultType="cn.zjut.mybatis.pojo.User">
        SELECT
          `id`,
          `username`,
          `birthday`,
          `sex`,
          `address`
        FROM `user`
        WHERE `id` = #{id}
    </select>
</mapper>

       编写测试代码

import cn.zjut.mybatis.pojo.User;
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 java.io.IOException;
import java.io.InputStream;

public class MybatisTest {
    @Test
    public void testGetUserById() throws IOException {
        //创建核心配置文件输入流
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //通过输入流创建 SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行查询 参数一:sql id 参数二:入参
        User user = sqlSession.selectOne("user.getUserById",1);
        System.out.println(user);
        //释放资源
        sqlSession.close();
    }
}

抽取SqlSessionFactory工具类

 

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

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

public class SqlSessionFactoryUtil {
    private static SqlSessionFactory sqlSessionFactory;
    /**
     * 静态代码块
     */
    static{
        try {
            //创建SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //获取关联核心配置文件的输入流
            InputStream inputStream;
            inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
            //通过核心配置文件输入流创建SqlSessionFactory对象
            sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取SqlSessionFactory对象
     * @return SqlSessionFactory
     */
    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }
}

       模糊查询

       sql配置

<select id="getUserByUserName" parameterType="string" resultType="cn.zjut.mybatis.pojo.User">
    SELECT
      `id`,
      `username`,
      `birthday`,
      `sex`,
      `address`
    FROM `user`
    <!--WHERE `username` like #{username}-->
    WHERE `username` LIKE '%${value}%'
</select>

       测试代码

@Test
public void testGetUserByUserName(){
    SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //List<User> list = sqlSession.selectList("user.getUserByUserName", "%张%");
    List<User> list = sqlSession.selectList("user.getUserByUserName", "张");
    for (User user : list) {
        System.out.println(user);
    }
}

       增添 一条记录

       sql配置

   <insert id="insertUser" parameterType="cn.zjut.mybatis.pojo.User">
   INSERT INTO `user`
               (`username`,
                 `birthday`,
                 `sex`,
                  `address`)
         VALUES
              (#{username},
               #{birthday},
               #{sex},
              #{address})
</insert>

       测试代码

@Test
public void testInsertUser(){
    SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    User user = new User();
    user.setUsername("张无名");
    user.setSex("1");
    user.setAddress("杭州西湖");
    user.setBirthday(new Date());
    sqlSession.insert("user.insertUser", user);
    //提交事务
    sqlSession.commit();
    sqlSession.close();
}

       插入数据设置主键返回 

       方式一sql配置

<!-- selectKey用于主键返回
 keyProperty用于绑定pojo属性
 resultType属性数据类型
 order什么时候执行 AFTER BEFORE
 SELECT LAST_INSERT_ID():得到最后一次插入数据的主键值,适用于自增型主键
-->
<insert id="insertUserKey" parameterType="cn.zjut.mybatis.pojo.User">
    <selectKey keyProperty="id" resultType="int" order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
    INSERT INTO `user`
                (`username`,
                `birthday`,
                `sex`,
                `address`)
          VALUES
                (#{username},
                #{birthday},
                #{sex},
                #{address})
</insert>

        方式二sql配置 

    <insert id="insertUserKey" parameterType="cn.zjut.mybatis.pojo.User" useGeneratedKeys="true" keyProperty="id">
<!--    <selectKey keyProperty="id" resultType="int" order="AFTER">
            SELECT LAST_INSERT_ID()
        </selectKey>-->
        INSERT INTO `user`
                    (`username`,
                    `birthday`,
                    `sex`,
                    `address`)
              VALUES
                    (#{username},
                    #{birthday},
                    #{sex},
                    #{address})
    </insert>

       返回UUID

       给用户表添加uuid2列,对应pojo添加uuid2字段

      sql配置

<!--如果配置selectKey则useGeneratedKeys不会生效-->
<insert id="insertUserUuid" parameterType="cn.zjut.mybatis.pojo.User" useGeneratedKeys="true" keyProperty="id">
    <selectKey keyProperty="uuid2" resultType="string" order="BEFORE">
        SELECT UUID()
    </selectKey>
    INSERT INTO `user`
    (`username`,
    `birthday`,
    `sex`,
    `address`,
    `uuid2`)
    VALUES
    (#{username},
    #{birthday},
    #{sex},
    #{address},
    #{uuid2})
</insert>

       修改数据

       sql配置

 

   <update id="updateUser" parameterType="cn.zjut.mybatis.pojo.User">
   UPDATE
     `user`
    SET
      username = #{username}
    WHERE `id` = #{id}
</update>

       测试代码

@Test
public void testUpdateUser(){
    SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    User user = new User();
    user.setId(30);
    user.setUsername("张角");
    sqlSession.update("user.updateUser", user);
    sqlSession.commit();
    sqlSession.close();
}

       删除数据

       sql配置

   <delete id="deleteUser" parameterType="int">
   DELETE
   FROM `user`
   WHERE `id` = #{id}
</delete>

      测试代码 

 

@Test
public void testDeleteUser(){
    SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    sqlSession.delete("user.deleteUser",30);
    sqlSession.commit();
    sqlSession.close();
}

 Mybatis架构图

Mybatis Dao开发方式

       传统Dao开发方式

       创建UserDao接口

import cn.zjut.mybatis.pojo.User;

import java.util.List;

public interface UserDao {
    User getUserById(Integer id);
    List<User> getUserByUserName(String userName);
    void insertUser(User user);
}

       创建UserDaoImpl接口实现类

import cn.zjut.mybatis.dao.UserDao;
import cn.zjut.mybatis.pojo.User;
import cn.zjut.mybatis.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

public class UserDaoImpl implements UserDao {
    @Override
    public User getUserById(Integer id) {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("user.getUserById", id);
        sqlSession.close();
        return user;
    }

    @Override
    public List<User> getUserByUserName(String userName) {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession.selectList("user.getUserByUserName", userName);
        sqlSession.close();
        return list;
    }

    @Override
    public void insertUser(User user) {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.insert("user.insertUser", user);
        sqlSession.commit();
        sqlSession.close();
    }
}

       创建UserDaoTest测试类

import cn.zjut.mybatis.dao.UserDao;
import cn.zjut.mybatis.dao.impl.UserDaoImpl;
import cn.zjut.mybatis.pojo.User;
import org.junit.Test;

import java.util.Date;
import java.util.List;

public class UserDaoTest {
    @Test
    public void testGetUserById() {
        UserDao userDao = new UserDaoImpl();
        User user = userDao.getUserById(28);
        System.out.println(user);
    }

    @Test
    public void testGetUserByUserName() {
        UserDao userDao = new UserDaoImpl();
        List<User> list = userDao.getUserByUserName("张");
        for (User user : list) {
            System.out.println(user);
        }
    }
    @Test
    public void testInsertUser() {
        UserDao userDao = new UserDaoImpl();
        User user = new User();
        user.setUsername("张飞6");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("杭州滨江");
        userDao.insertUser(user);
    }
}

       接口动态代理方式开发Dao

       创建映射文件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">
<mapper namespace="cn.zjut.mybatis.mapper.UserMapper">
    <!--
    动态代理开发原则
    1.namespace必须是接口得全路径名
    2.接口方法名必须与sql id一致
    3.接口方法入参必须与parameterType一致
    4.接口方法返回值类型必须与resultType类型一致
    -->
    <select id="getUserById" parameterType="int" resultType="cn.zjut.mybatis.pojo.User">
        SELECT
          `id`,
          `username`,
          `birthday`,
          `sex`,
          `address`
        FROM `user`
        WHERE `id` = #{id}
    </select>
    <select id="getUserByUserName" parameterType="string" resultType="cn.zjut.mybatis.pojo.User">
        SELECT
          `id`,
          `username`,
          `birthday`,
          `sex`,
          `address`
        FROM `user`
        <!--WHERE `username` like #{username}-->
        WHERE `username` LIKE '%${value}%'
    </select>
    <insert id="insertUser" parameterType="cn.zjut.mybatis.pojo.User">
      INSERT INTO `user`
                  (`username`,
                    `birthday`,
                    `sex`,
                     `address`)
            VALUES
                 (#{username},
                  #{birthday},
                  #{sex},
                 #{address})
   </insert>
</mapper>

       在核心配置文件中加载映射文件

      

       按照动态代理开发规则创建UserMapper接口 

import cn.zjut.mybatis.pojo.User;

import java.util.List;

public interface UserMapper {
    User getUserById(Integer id);
    List<User> getUserByUserName(String userName);
    void insertUser(User user);
}

       创建UserMapperTest测试类

import cn.zjut.mybatis.mapper.UserMapper;
import cn.zjut.mybatis.pojo.User;
import cn.zjut.mybatis.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;

import java.util.Date;
import java.util.List;

public class UserMapperTest {
    @Test
    public void testGetUserById() {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取接口代理实现类
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(28);
        System.out.println(user);
        sqlSession.close();
        }
    @Test
    public void testGetUserByUserName() {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取接口代理实现类
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = userMapper.getUserByUserName("张");
        for (User user : list) {
            System.out.println(user);
        }
        sqlSession.close();
    }
    @Test
    public void testInsertUser() {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取接口代理实现类
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUsername("赵子龙");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("杭州富阳");
        userMapper.insertUser(user);
        sqlSession.commit();
        sqlSession.close();
    }
}

 SqlMapConf.xml配置

       配置内容顺序如下

      

       properties 

<?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">
      <property name="jdbc.username" value="root"/>
      <property name="jdbc.password" value="1234"/>
   </properties>
   <!-- 和spring整合后 environments配置将废除 -->
   <environments default="development">
      <environment id="development">
         <!-- 使用jdbc事务管理 -->
         <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="user.xml"/>
      <mapper resource="UserMapper.xml"/>
   </mappers>

</configuration>

        jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=1234

       typeAliases

       Mybatis支持的别名

       别名                 映射类型

       _byte               byte

       _long               long

       _short             short

       _int                 int

       _integer          int

       _double          double

       _float              float

      _boolean        boolean

      string              String

      byte                Byte

      long                Long

      short              Short

      int                   Integer

      integer            Integer

      double            Double

      float                Float

      boolean          Boolean

      date                Date

      decimal          BigDecimal

      bigdecimal     BigDecimal

      map               Map

    

<typeAliases>
   <!-- 单个类别名设置 别名使用不区分大小写 -->
   <!--<typeAlias type="cn.zjut.mybatis.pojo.User" alias="user"/>-->
   <!-- 别名包扫描 别名是类的全称不区分大小写 -->
   <package name="cn.zjut.mybatis.pojo"/>
</typeAliases>

       mappers

<!--加载映射文件-->
<mappers>
   <!-- 第一种方式加载resource文件 -->
   <mapper resource="user.xml"/>
   <!--<mapper resource="UserMapper.xml"/>-->
   <!--
   第二种方式class扫描器加载
      1.映射文件和接口文件必须在同一目录
      2.映射文件和接口文件文件名必须保持一致
      -->
   <!--<mapper class="cn.zjut.mybatis.mapper.UserMapper"/>-->
   <!-- 第三种方式包扫描器
       1.映射文件和接口文件必须在同一目录
       2.映射文件和接口文件文件名必须保持一致
   -->
   <package name="cn.zjut.mybatis.mapper"/>
</mappers>

 

 

 

 

       

 

 

      

 

 

 

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值