• MyBatis入门(一)—— 入门案例


    一、MyBatis简介

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

      与Hibernate比较:

    1.Hibernate学习门槛不低,要精通门槛更高。门槛高在怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate缓存与数据加载策略方面需要你的经验和能力都很强才行。国内目前前的情况精通hibernate技术大牛非常少。

    2.sql优化方面,Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。当然了,Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。说得更深入一些,如果有个查询要关联多张表,比如5张表,10张表时,而且,我们要取的字段只是其中几张表的部分字段。这时用hibernate时就会显得非常力不从心。就算用hibernate的sqlquery,后续的维护工作也会让人发狂。

    二、入门案例

    1、数据库的准备(创表语句)

     
     1 -- ----------------------------
     2 -- Table structure for `user`
     3 -- ----------------------------
     4 DROP TABLE IF EXISTS `user`;
     5 CREATE TABLE `user` (
     6   `id` int(11) NOT NULL AUTO_INCREMENT,
     7   `username` varchar(32) NOT NULL COMMENT '用户名称',
     8   `birthday` date DEFAULT NULL COMMENT '生日',
     9   `sex` char(1) DEFAULT NULL COMMENT '性别',
    10   `address` varchar(256) DEFAULT NULL COMMENT '地址',
    11   PRIMARY KEY (`id`)
    12 ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
    13 
    14 -- ----------------------------
    15 -- Records of user
    16 -- ----------------------------
    17 INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
    18 INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
    19 INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
    20 INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州');
    21 INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
    22 INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州');
    23 INSERT INTO `user` VALUES ('26', '王五', null, null, null);
     

    2、使用idea新建maven-archetype-quickstart项目

    3、引入依赖

     
     1 <dependency>
     2       <groupId>mysql</groupId>
     3       <artifactId>mysql-connector-java</artifactId>
     4       <version>5.1.45</version>
     5 </dependency>
     6 <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
     7 <dependency>
     8       <groupId>org.mybatis</groupId>
     9       <artifactId>mybatis</artifactId>
    10       <version>3.2.7</version>
    11 </dependency>
     

    4、于resources文件夹中创建SqlMapConfig.xml

     
     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE configuration
     3         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
     4         "http://mybatis.org/dtd/mybatis-3-config.dtd">
     5 <configuration>
     6     <!-- 和spring整合后 environments配置将废除 -->
     7     <environments default="development">
     8         <environment id="development">
     9             <!-- 使用jdbc事务管理 -->
    10             <transactionManager type="JDBC" />
    11             <!-- 数据库连接池 -->
    12             <dataSource type="POOLED">
    13                 <property name="driver" value="com.mysql.jdbc.Driver" />
    14                 <property name="url"
    15                           value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
    16                 <property name="username" value="root" />
    17                 <property name="password" value="" />
    18             </dataSource>
    19         </environment>
    20     </environments>
    21 
    22     <mappers>
    23         <!-- 第一种方式,加载 resource-->
    24         <mapper resource="User.xml"></mapper>
    25         <mapper resource="UserMapper.xml"/>
    26 
    27         <!-- 第三种方式,包扫描器要求(推荐使用此方式):
    28              1、映射文件与接口同一目录下
    29              2、映射文件名必需与接口文件名称一致
    30         -->
    31         <!--<package name="com.cenobitor.mapper"/>-->
    32     </mappers>
    33 </configuration>
     

    5、创建实体类User

     
     1 package com.cenobitor.pojo;
     2 
     3 import java.util.Date;
     4 
     5 public class User {
     6 
     7     private Integer id;
     8     private String username;// 用户姓名
     9     private String sex;// 性别
    10     private Date birthday;// 生日
    11     private String address;// 地址
    12     private String uuid;
    13 
    14     ......
    15 }
    复制代码

    6、配置SQL查询的映射文件(resources目录)

    复制代码
     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE mapper
     3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
     5 <!-- namespace:命名空间,类似于java包,主要用于隔离sql语句的,后续有重要作用
     6      #{}:占位符,相当于jdbc的?
     7      ${}:字符串拼接指令,注意如果入参为普通数据类型时,括号里面只能写value
     8  -->
     9 <mapper namespace="user">
    10     <!-- id:sql id标识sql语句的唯一标识
    11              parameterType:入参的数据类型
    12              resultType:返回结果的数据类型
    13     -->
    14     <select id="getUserById" parameterType="int" resultType="com.cenobitor.pojo.User">
    15         SELECT
    16           `id`,
    17           `username`,
    18           `birthday`,
    19           `sex`,
    20           `address`
    21         FROM `user`
    22         WHERE id = #{id}
    23     </select>
    24 
    25     <!-- resultType:如果返回结果是集合时,只需要设置为元素的数据类型就可 -->
    26     <select id="getUserByName" parameterType="String" resultType="com.cenobitor.pojo.User">
    27         SELECT
    28           `id`,
    29           `username`,
    30           `birthday`,
    31           `sex`,
    32           `address`
    33         FROM `user`
    34         WHERE username LIKE '%${value}%'
    35     </select>
    36     
    37     <insert id="insertUser" parameterType="com.cenobitor.pojo.User">
    38         INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
    39         VALUES (#{username},#{birthday},#{sex},#{address})
    40     </insert>
    41 
    42     <!--返回MySql自增主键-->
    43     <!-- useGeneratedKeys:标识插入使用自增id
    44          keyProperty:与useGeneratedKeys配套使用,用于绑定主键接收的pojo属性
    45      -->
    46     <insert id="insertUserKey" parameterType="com.cenobitor.pojo.User"
    47             useGeneratedKeys="true" keyProperty="id">
    48 
    49         <!-- selectKey:用于配置主键返回
    50                       keyProperty:要绑定的pojo属性
    51                       resultType:属性数据类型
    52                       order:指定什么时候执行,AFTER之后
    53                  -->
    54         <!-- <selectKey keyProperty="id" resultType="int" order="AFTER">
    55              SELECT LAST_INSERT_ID()
    56         </selectKey> -->
    57 
    58         INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
    59         VALUES (#{username},#{birthday},#{sex},#{address})
    60     </insert>
    61 
    62     <!--返回MySql的uuid返回主键-->
    63     <insert id="insertUserUUID" parameterType="com.cenobitor.pojo.User">
    64 
    65         <!-- selectKey:用于配置主键返回
    66                       keyProperty:要绑定的pojo属性
    67                       resultType:属性数据类型
    68                       order:指定什么时候执行,AFTER之后
    69                  -->
    70         <selectKey keyProperty="uuid" resultType="String" order="BEFORE">
    71              SELECT UUID()
    72         </selectKey>
    73 
    74         INSERT INTO USER (`username`,`birthday`,`sex`,`address`,`uuid`)
    75         VALUES (#{username},#{birthday},#{sex},#{address},#{uuid})
    76     </insert>
    77     
    78     <update id="updateUser" parameterType="com.cenobitor.pojo.User">
    79         UPDATE USER SET username = #{username} WHERE id = #{id}
    80     </update>
    81     
    82     <delete id="deleteUser" parameterType="com.cenobitor.pojo.User">
    83         DELETE FROM `user` WHERE `id` = #{id}
    84     </delete>
    85 
    86 </mapper>
     

    7、加载映射文件,在SqlMapConfig.xml配置mappers节点

    8、编写测试类

     
      1 package com.cenobitor;
      2 
      3 import com.cenobitor.Utils.SqlSessionFactoryUtils;
      4 import com.cenobitor.pojo.User;
      5 import junit.framework.Test;
      6 import junit.framework.TestCase;
      7 import junit.framework.TestSuite;
      8 import org.apache.ibatis.io.Resources;
      9 import org.apache.ibatis.session.SqlSession;
     10 import org.apache.ibatis.session.SqlSessionFactory;
     11 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
     12 
     13 import java.io.IOException;
     14 import java.io.InputStream;
     15 import java.util.Date;
     16 import java.util.List;
     17 
     18 /**
     19  * Unit test for simple App.
     20  */
     21 public class AppTest extends TestCase {
     22     //根据id查找用户
     23     public void testGetUserById() throws IOException {
     24 
     25         //创建SqlSessionFactoryBuilder对象
     26         SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
     27         //查找配置文件,创建输入流
     28         InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
     29         //加载配置文件,创建SqlSessionFactory
     30         SqlSessionFactory sqlSessionFactory = sfb.build(inputStream);
     31         //创建SqlSession
     32         SqlSession sqlSession = sqlSessionFactory.openSession();
     33         //执行查询,参数一:要查询的statementId,参数二:sql语句入参
     34         User user = sqlSession.selectOne("user.getUserById", 1);
     35         //输入查询结果
     36         System.out.println(user);
     37 
     38         //释放资源
     39         sqlSession.close();
     40     }
     41 
     42     //根据用户名查找用户列表
     43     public void testGetUserByName(){
     44         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
     45         SqlSession sqlSession = sqlSessionFactory.openSession();
     46         List<User> list = sqlSession.selectList("user.getUserByName", "张");
     47         for (User user : list) {
     48             System.out.println(user);
     49         }
     50 
     51         sqlSession.close();
     52     }
     53 
     54     //插入用户
     55     public void testInsertUser(){
     56         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
     57         SqlSession sqlSession = sqlSessionFactory.openSession();
     58 
     59         User user = new User();
     60         user.setUsername("貂蝉");
     61         user.setSex("0");
     62         user.setBirthday(new Date());
     63         user.setAddress("吕布");
     64 
     65         //执行插入语句
     66         sqlSession.insert("user.insertUser",user);
     67         //提交事务
     68         sqlSession.commit();
     69         //释放资源
     70         sqlSession.close();
     71     }
     72 
     73     //Mysql自增返回
     74     public void testInsertUserKey(){
     75         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
     76         SqlSession sqlSession = sqlSessionFactory.openSession();
     77 
     78         User user = new User();
     79         user.setUsername("杨玉环");
     80         user.setSex("0");
     81         user.setBirthday(new Date());
     82         user.setAddress("李隆基");
     83 
     84         //执行插入语句
     85         sqlSession.insert("user.insertUserKey", user);
     86         System.out.println(user);
     87         //提交事务
     88         sqlSession.commit();
     89         //释放资源
     90         sqlSession.close();
     91     }
     92 
     93     //Mysql的uuid返回主键
     94     //注:在使用uuid之前数据库user表要先加上uuid2字段、user的pojo也要加上相应属性
     95     public void testInsertUserUUID(){
     96         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
     97         SqlSession sqlSession = sqlSessionFactory.openSession();
     98 
     99         User user = new User();
    100         user.setUsername("孙尚香");
    101         user.setSex("0");
    102         user.setBirthday(new Date());
    103         user.setAddress("刘备");
    104 
    105         //执行插入语句
    106         sqlSession.insert("user.insertUserUUID", user);
    107         System.out.println(user);
    108         //提交事务
    109         sqlSession.commit();
    110         //释放资源
    111         sqlSession.close();
    112     }
    113 
    114     //修改用户
    115     public void testUpdateUser(){
    116         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
    117         SqlSession sqlSession = sqlSessionFactory.openSession();
    118 
    119         User user = new User();
    120         user.setUsername("吕雉");
    121         user.setId(32);
    122 
    123         //执行插入语句
    124         sqlSession.update("user.updateUser",user);
    125 
    126         //提交事务
    127         sqlSession.commit();
    128         //释放资源
    129         sqlSession.close();
    130     }
    131 
    132     //删除用户
    133     public void testDeleteUser(){
    134         SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
    135         SqlSession sqlSession = sqlSessionFactory.openSession();
    136         sqlSession.delete("user.deleteUser",32);
    137         sqlSession.commit();
    138         sqlSession.close();
    139     }
    140 }
     

    9、抽取SqlSessionFactoryUtils工具类,共享SqlSessionFactory的对象

     
     1 public class SqlSessionFactoryUtils {
     2     private SqlSessionFactoryUtils(){}
     3 
     4     private static class SqlSessionFactoryInstance{
     5 
     6         public static SqlSessionFactory sqlSessionFactory;
     7 
     8         static {
     9             try {
    10                 sqlSessionFactory =  new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml"));
    11             } catch (IOException e) {
    12                 e.printStackTrace();
    13             }
    14         }
    15     }
    16 
    17     public static SqlSessionFactory getSqlSessionFactory(){
    18         return SqlSessionFactoryInstance.sqlSessionFactory;
    19     }
    20 
    21 }
     

    三、MyBatis架构图

    四、MyBatis 动态代理Dao开发 

     1、开发规则

    • namespace必须是接口的全路径名
    • 接口的方法名必须与映射文件的sql id 一致
    • 接口的输入参数必须与映射文件的parameterType类型一致
    • 接口的返回类型必须与映射文件的resultType类型一致

    2、动态代理Dao开发步骤

    ①创建UserMapper.xml映射文件

     
     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE mapper
     3         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     4         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
     5 <mapper namespace="com.cenobitor.mapper.UserMapper">
     6 
     7     <select id="getUserById" parameterType="int" resultType="com.cenobitor.pojo.User">
     8         SELECT
     9           `id`,
    10           `username`,
    11           `birthday`,
    12           `sex`,
    13           `address`
    14         FROM `user`
    15         WHERE id = #{id}
    16     </select>
    17 
    18     <select id="getUserByName" parameterType="String" resultType="com.cenobitor.pojo.User">
    19         SELECT
    20           `id`,
    21           `username`,
    22           `birthday`,
    23           `sex`,
    24           `address`
    25         FROM `user`
    26         WHERE username LIKE '%${value}%'
    27     </select>
    28     
    29     <insert id="insertUser" parameterType="com.cenobitor.pojo.User">
    30         INSERT INTO USER (`username`,`birthday`,`sex`,`address`)
    31         VALUES (#{username},#{birthday},#{sex},#{address})
    32     </insert>
    33 
    34 </mapper>
     

    ②创建UserMapper接口

     
     1 package com.cenobitor.mapper;
     2 
     3 import com.cenobitor.pojo.User;
     4 import java.util.List;
     5 
     6 public interface UserMapper {
     7 
     8     /**根据用户ID查询用户信息
     9      * @param id
    10      * @return
    11      */
    12     User getUserById(Integer id);
    13 
    14     /**
    15      * 根据用户名查找用户列表
    16      * @param name
    17      * @return
    18      */
    19     List<User> getUserByName(String name);
    20 
    21     /**
    22      * 添加用户
    23      * @param user
    24      */
    25     void insertUser(User user);
    26 
    27 }
     

    ③加载UserMpper.xml

     

    ④建立测试类

     
     1 public class UserMapperTest {
     2 
     3     @Test
     4     public void getUserById() {
     5         SqlSessionFactory sqlSessionFactory =
     6                 SqlSessionFactoryUtils.getSqlSessionFactory();
     7         SqlSession sqlSession = sqlSessionFactory.openSession();
     8         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
     9         User user = mapper.getUserById(31);
    10         System.out.println(user);//User{id=31, username='杨玉环', sex='0', birthday=Sat Apr 07 00:00:00 CST 2018, address='李隆基', uuid='null'}
    11         sqlSession.close();
    12     }
    13 
    14     @Test
    15     public void getUserByName() {
    16         SqlSessionFactory sqlSessionFactory =
    17                 SqlSessionFactoryUtils.getSqlSessionFactory();
    18         SqlSession sqlSession = sqlSessionFactory.openSession();
    19         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    20         List<User> users = mapper.getUserByName("张");
    21         for (User user : users) {
    22             System.out.println(user);
    23         }
    24         /*User{id=10, username='张三', sex='1', birthday=Thu Jul 10 00:00:00 CST 2014, address='北京市', uuid='null'}
    25         User{id=16, username='张小明', sex='1', birthday=null, address='河南郑州', uuid='null'}
    26         User{id=24, username='张三丰', sex='1', birthday=null, address='河南郑州', uuid='null'}*/
    27         sqlSession.close();
    28     }
    29 
    30     @Test
    31     public void insertUser() {
    32         SqlSessionFactory sqlSessionFactory =
    33                 SqlSessionFactoryUtils.getSqlSessionFactory();
    34         SqlSession sqlSession = sqlSessionFactory.openSession();
    35         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    36         User user = new User();
    37         user.setUsername("lisi");
    38         user.setSex("1");
    39         user.setBirthday(new Date());
    40         user.setAddress("北京");
    41         mapper.insertUser(user);
    42         sqlSession.commit();
    43         sqlSession.close();
    44     }
    45 }
     

    五、SqlMapConfig.xml配置

    1、properties

    ①属于核心文件配置

    1 <!-- 加载规则,首先加载标签内部属性,再加载外部文件,名称相同时,会替换相同名称的内容 -->
    2     <properties resource="jdbc.properties">
    3         <property name="jdbc.username" value="root1"/>
    4         <property name="jdbc.password" value="root"/>
    5     </properties>

    ②jdbc.properties

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

    2、typeAliases

    自定义别名

     
    1 <typeAliases>
    2         <!-- 单个别名定义 -->
    3         <!-- <typeAlias type="com.itheima.mybatis.pojo.User" alias="user"/> -->
    4         <!-- 别名包扫描器(推荐使用此方式),整个包下的类都被定义别名,别名为类名,不区分大小写-->
    5         <package name="com.itheima.mybatis.pojo"/>
    6 </typeAliases>
     

    3、mapper

     
     1 <mappers>
     2         <!-- 第一种方式,加载 resource-->
     3         <mapper resource="mapper/user.xml"/>
     4         <!-- <mapper resource="mapper/UserMapper.xml"/> -->
     5 
     6         <!-- 第二种方式,class扫描器要求:
     7              1、映射文件与接口同一目录下
     8              2、映射文件名必需与接口文件名称一致
     9          -->
    10         <!-- <mapper class="com.itheima.mybatis.mapper.UserMapper"/> -->
    11 
    12         <!-- 第三种方式,包扫描器要求(推荐使用此方式):
    13              1、映射文件与接口同一目录下
    14              2、映射文件名必需与接口文件名称一致
    15         -->
    16         <package name="com.itheima.mybatis.mapper"/>
    17 </mappers>
     

     六、小结

    1、#{} 和${}

    #{} 表示一个占位符号,通过#{} 可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{} 可以有效防止sql注入。#{}可以接受简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其他名称。

    ${}表示拼接sql串,通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接受简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。

    2、parameterType和resultype

    parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。

    resultType:指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中。

  • 相关阅读:
    新年后的第一个学习总结
    2021/02/07周学习总结
    内网穿透
    有效的括号
    实现一个简单的模板字符串替换
    二叉树的最大深度
    前端性能和错误监控
    前端缓存
    display: none; opacity: 0; visibility: hidden;
    发布订阅模式与观察者模式
  • 原文地址:https://www.cnblogs.com/liuys635/p/12565897.html
Copyright © 2020-2023  润新知