初识Mybatis(概念、配置、映射文件和CRUD)

一、Mybatis 概念介绍

​ MyBatis 是一款优秀的持久层(Dao)框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

  • 特点:
    • 定制化SQL
    • 支持存储过程(数据库脚本)调用
    • 高级映射

二、ORM-对象关系映射

  • 针对关系库 - 实体对象映射
    • 表 实体类
    • 字段 成员属性
    • 表记录 类对象

三、自动化 VS 半自动化 ORM 框架

  • 半自动化 ORM 框架:Mybatis
    1. 数据库表结构需要手动创建
    2. 依赖于数据库平台
    3. sql 语句需要开发人员编写
    4. 优势:
      1. sql 语句有开发人员编写 后期优化比较方便
      2. 适合传统项目 ,用于需求变化高的项目(互联网项目 电商 金融项目…)
      3. 市面用的最多的一套持久层框架
  • 自动化ORM框架:Hibernate
    1. 可以通过框架来创建
    2. 不依赖具体的数据库平台
    3. 可以实现基本的CRUD 而不提供sql 直接调用API 方法即可
    4. 缺点:
      1. 表数据量较大时 查询效率比较低
      2. 用于需求变化不高的项目 传统型项目(OA 后端管理 ERP 系统…)
      3. 学习成本较高(实体与实体之间映射 sql 优化)

四、Mybatis 环境搭建与测试

1.创建Maven 普通项目

2.添加坐标

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!-- mybatis jar 包依赖 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.1</version>
    </dependency>

    <!-- 数据库驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.39</version>
    </dependency>
    <!-- log4j日志打印 -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.16</version>
    </dependency>

</dependencies>
  
<build>
    <!--
          Maven 项目
             如果源代码(src/main/java)存在xml properties tld 等文件,maven 默认不会自动编译该文件到输出目录
             如果要编译源代码中xml properties tld 等文件,需要显式配置resources 标签
        -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
                <include>**/*.tld</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

3.添加日志log4j.properties 文件

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

4.添加全局配置文件 mybatis.xml

文件模板参考官网 https://mybatis.org/mybatis-3/zh/getting-started.html

<?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>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--
        sql 映射文件 加载配置
    -->
    <mappers>
        <mapper resource="com/xyz/mappers/UserMapper.xml"/>
    </mappers>
</configuration>

5.添加sql 映射文件 UserMapper.xml

映射文件模本配置 https://mybatis.org/mybatis-3/zh/getting-started.html

<?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:命名空间属性
             值唯一  在整个应用程序中不允许出现相同的命名空间  规则:包名.文件名
    -->
<mapper namespace="com.xyz.mappers.UserMapper">
    <!--
       select 标签:查询标签
           id:用于区分同一个xml 文件不同的标签  同文件下 标签id 值唯一
           resultType:输出结果类型
           parameterType:输入参数类型
           标签体:待执行的sql 语句   #{}:参数占位符  类似于 原生的sql 中? 占位符
    -->
    <select id="queryUserByUserId" parameterType="int" resultType="com.xyz.vo.User">
        select id, user_name as userName, user_pwd as userPwd, flag, create_time as createTime 
        from user 
        where id=#{id}
    </select>

</mapper>

6.执行测试

 @Test
public void test() throws IOException {
    /**
         a)、读取mybatis的配置文件
         b)、加载配置文件创建SqlSessionFactory
         c)、根据SqlSessionFactory创建SqlSession
         d)、通过sqlSession操作数据库
         e)、处理结果
         f)、关闭session
         */
    String file = "mybatis.xml";
    InputStream is= Resources.getResourceAsStream(file);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    SqlSession session = sqlSessionFactory.openSession();
    /**
         * 参数1-statement:待执行的某个sql 对应的标签具体路径  namespace.标签id
         * 参数2:参数值
         */
    User user= session.selectOne("com.xyz.mappers.UserMapper.queryUserByUserId",75);
    System.out.println(user);
    session.close();
}

五、Mybatis 映射文件-输入输出参数

输入参数

  • parameterType:
    • 基本类型(4类8种)
    • 常见类型(String、日期)
    • JavaBean
    • 集合(List 、Map)
    • 数组
<!--
    parameterType:输入参数类型 基本类型(四类八种) 常见类型(String 日期) JavaBean 集合(List Map) 数组
    -->
 <select id="queryUserByUserId" parameterType="int" resultType="User">
     select id, user_name as userName, user_pwd as userPwd, flag, create_time as createTime 
     from user 
     where id=#{id}
</select>

<select id="queryUserByUserName" parameterType="string" resultType="User">
    select id, user_name as userName, user_pwd as userPwd, flag, create_time as createTime
    from user 
    where user_name=#{userName}
</select>

<select id="queryUserByUserNameAndUserPwd" parameterType="UserQuery" resultType="User">
    select id, user_name as userName, user_pwd as userPwd, flag, create_time as createTime
    from user 
    where user_name=#{userName} and user_pwd=#{userPwd}
</select>

<select id="queryUserByUserNameAndUserPwdMap" parameterType="map" resultType="User">
    select id, user_name as userName, user_pwd as userPwd, flag, create_time as createTime
    from user
    where user_name=#{userName} and user_pwd=#{userPwd}
</select>

<delete id="deleteUsersByIds" >
    delete from user where id in
    <!-- collection:array|list -->
    <foreach collection="array" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</delete>

<delete id="deleteUsersByIds02" >
    delete from user where id in
    <!-- collection:array|list -->
    <foreach collection="list" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</delete>

<delete id="deleteUsersByIds03"  parameterType="map">
    delete from user where id in
    <!--
          collection:array|list
              如果参数类型为map:map key对应的value 为数组或list,此时collection值为key 名称
        -->
    <foreach collection="ids" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</delete>

输出参数(结果)

  • resultType(输出结果类型):基本类型(四类八种) String|日期 JavaBean List Map List<Map>
  • resultMap
<!--
    resultType:输出结果类型    基本类型(四类八种)  String|日期   JavaBean   List  Map  List<Map>
    -->
<sql id="user_columns">
    id, user_name as userName, user_pwd as userPwd, flag, create_time as createTime
</sql>
<select id="queryUserNameById" parameterType="int" resultType="string">
    select user_name from user where id=#{id}
</select>

<select id="queryUserIdByUserName" parameterType="string" resultType="int">
    select id from user where user_name=#{userName}
</select>

<select id="queryUsersByUserName" parameterType="string" resultType="User">
    select <include refid="user_columns"/> from user 
    where user_name like concat('%',#{userName},'%')
</select>

<select id="queryUserByIdMap" parameterType="int" resultType="map" >
    select <include refid="user_columns"/> from user where id=#{id}
</select>

<select id="queryUsersByUserNameListMap" parameterType="string" resultType="map" >
    select <include refid="user_columns"/> from user 
    where user_name like concat('%',#{userName},'%')
</select>
  • Map List<Map>
    • Map 5种遍历方式
Map<String,Object> result = session.selectOne("com.xyz.mappers.UserMapper.queryUserByIdMap",75);    
System.out.println("---------------------");
for(String key: result.keySet()){
    System.out.println(key+"--"+result.get(key));
}
System.out.println("---------------------");

for(Map.Entry<String,Object> entry:result.entrySet()){
    System.out.println(entry.getKey()+"--"+entry.getValue());
}

System.out.println("---------------------");
result.keySet().forEach(k->{
    System.out.println(k+"--"+result.get(k));
});

System.out.println("---------------------");
result.entrySet().forEach(e->{
    System.out.println(e.getKey()+"--"+e.getValue());
});

System.out.println("---------------------");
result.forEach((k,v)->{
    System.out.println(k+"--"+v);
});    
    • List<Map> 遍历
List<Map<String,Object>> results= session.selectList("com.xyz.mappers.UserMapper.queryUsersByUserNameListMap","test");

System.out.println("---------------------");
results.forEach(result->{
    for(String key: result.keySet()){
        System.out.println(key+"--"+result.get(key));
    }
});

System.out.println("---------------------");
results.forEach(result->{
    for(Map.Entry<String,Object> entry:result.entrySet()){
        System.out.println(entry.getKey()+"--"+entry.getValue());
    }
});

System.out.println("---------------------");
results.forEach(result->{
    result.keySet().forEach(k->{
        System.out.println(k+"--"+result.get(k));
    });
});

System.out.println("---------------------");
results.forEach(result->{
    result.entrySet().forEach(e->{
        System.out.println(e.getKey()+"--"+e.getValue());
    });
});

System.out.println("---------------------");
results.forEach(result->{
    result.forEach((k,v)->{
        System.out.println(k+"--"+v);
    });
});

六、Mybatis CRUD 标签配置

  • Select Insert Update Delete
<!--
     insert:添加记录标签
          添加记录返回影响行数
          添加记录返回主键
          批量添加
    -->
<insert id="saveUser" parameterType="User" >
    insert into user(user_name, user_pwd, flag, create_time) 
    values (#{userName},#{userPwd},#{flag},#{createTime})
</insert>

<!--
     添加记录返回主键01
          useGeneratedKeys:true mybatis 执行添加时 获取添加后的主键值
          keyProperty:id  主键值 映射到User  id 变量
    -->
<insert id="saveUserHasKey" parameterType="User" useGeneratedKeys="true"  keyProperty="id">
    insert into user(user_name, user_pwd, flag, create_time) 
    values (#{userName},#{userPwd},#{flag},#{createTime})
</insert>

<!--
     添加记录返回主键02
         添加字标签  selectKey
              order:BEFORE|AFTER  指定获取主键在SQL执行前(BEFORE) 还是执行后(AFTER)
              keyProperty
              resultType
         mysql
              select last_insert_id()
        oracle
             SELECT LOGS_SEQ.nextval AS ID FROM DUAL
    -->
<insert id="saveUserHasKey02" parameterType="User">
    <selectKey order="AFTER" keyProperty="id" resultType="int">
        select last_insert_id()
    </selectKey>
    insert into user(user_name, user_pwd, flag, create_time) 
    values (#{userName},#{userPwd},#{flag},#{createTime})
</insert>

<insert id="saveUserBatch" parameterType="list">
    insert into  user(user_name, user_pwd, flag, create_time) values
    <foreach collection="list" item="item" separator=",">
        (#{item.userName},#{item.userPwd},#{item.flag},#{item.createTime})
    </foreach>
</insert>

<!--
     update:
          单条记录更新
          批量更新
    -->
<update id="updateUser" parameterType="User">
    update user set user_name=#{userName},user_pwd=#{userPwd},flag=#{flag} where id=#{id}
</update>

<update id="updateUserPwdByIdsBatch" parameterType="map">
    update user set user_pwd=#{userPwd}
    where id in
    <foreach collection="ids" item="item" open="(" separator="," close=")" >
        #{item}
    </foreach>
</update>

<delete id="deleteUsersByIds03"  parameterType="map">
    delete from user where id in
    <!--
         collection:array|list
              如果参数类型为map  map key对应的value 为数组或list  此时collection值为key 名称
        -->
    <foreach collection="ids" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</delete>

七、基于接口代理的CRUD(重点)

  • 理解接口代理的CRUD 规范:
    1. mapper.xml中 namespace等于接口类全限定名
    2. mapper.java接口中的方法名必须与mapper.xml中statement id 一致
    3. mapper.java 输入参数类型必须与mapper.xml中statement 的parameterType参数类型一致
    4. mapper.java 中方法的返回值类型必须与mapper.xml 中对应statement 返回值类型一致。
    5. 接口名 与映射文件名称 一致(非集成环境)
    6. 映射文件与接口处于同一个包中(非集成环境)

1.定义接口(包 -com.xyz.mappers)

import com.xyz.query.AccountQuery;
import com.xyz.vo.Account;

import java.util.List;

public interface AccountMapper {
    public Account queryAccountById(Integer id);

    public List<Account> queryAccountsByParams(AccountQuery accountQuery);

}

2.定义映射文件(包 -com.xyz.mappers)

<?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.xyz.mappers.AccountMapper">

    <sql id="account_columns">
        id, aname, type, money, user_id as userId, create_time as createTime, update_time as updateTime, remark
    </sql>
    
    <select id="queryAccountById" parameterType="int" resultType="Account">
        select <include refid="account_columns"/>
        from  account
        where id=#{id}
    </select>

    <select id="queryAccountsByParams" parameterType="AccountQuery" resultType="com.xyz.vo.Account">
        select <include refid="account_columns"/>
        from account 
        where aname like concat('%',#{aname},'%') and type=#{type}
    </select>
</mapper>

3.添加映射文件到全局文件mybatis.xml

<mappers>
    <mapper resource="com/xyz/mappers/UserMapper.xml"/>
    <mapper resource="com/xyz/mappers/AccountMapper.xml"></mapper>
</mappers>

4.执行测试

public class TestAccuntMapper {
    private SqlSessionFactory factory;

    @Before
    public void init() throws IOException {
        String file = "mybatis.xml";
        InputStream is = Resources.getResourceAsStream(file);
        factory = new SqlSessionFactoryBuilder().build(is);
    }

    @Test
    public void test01() {
        SqlSession session = factory.openSession();
        // 获取接口的代理对象
        AccountMapper accountMapperProxy = session.getMapper(AccountMapper.class);
        Account account = accountMapperProxy.queryAccountById(142);
        System.out.println(account);
        session.close();
    }
    
    @Test
    public void test02() {
        SqlSession session = factory.openSession();
        // 获取接口的代理对象
        AccountMapper accountMapperProxy = session.getMapper(AccountMapper.class);
        AccountQuery accountQuery=new AccountQuery();
        accountQuery.setAname("test");
        accountQuery.setType("1");
        // 常用函数式接口  Consumer | BiConsumer   | Predicate | Function
        // 接口默认方法 foreach  sort 默认方法
        accountMapperProxy.queryAccountsByParams(accountQuery).forEach(a->{
            System.out.println(a);
        });
        session.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值