mybatis_基本使用

mybatis

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.2</version>
</dependency>

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>

1、第一个mybaits程序

1.1、搭建环境

CREATE DATABASE mybatis;

CREATE TABLE `user`(
   `id` INT(20) NOT NULL PRIMARY KEY,
   `name` VARCHAR(30) DEFAULT NULL,
   `pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,'张三','123456'),
(2,'李四','123456'),
(3,'王五','123456') 

新建项目

1.2mybatis创建

  • 创建SqlSession的工具类
package top.mgy.utils;

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 java.io.InputStream;

/**
 * mybatis 工具类
 *
 * 读取 sqlSessionFactory
 */
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream in = Resources.getResourceAsStream(resource);
             sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 获取 SqlSession
     * @return
     */
    public SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

1.3、编写代码

  • 实体类
package top.mgy.pojo;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class User {
    private int id;
    private String name;
    private String pwd;
}

  • Dao接口
package top.mgy.dao;

import top.mgy.pojo.User;

import java.util.List;

public interface UserDao {

    List<User> getUserList();
}

  • 核心配置 mybatis-config.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>
    <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://localhost:3306/mp?useUnicode=true&amp;charcaterEncoding=uft8&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="top/mgy/dao/UserMapper.xml"/>
    </mappers>
</configuration>
  • 接口实现类 替换为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=绑定一个对应的Dao/Mapper接口 -->
<mapper namespace="top.mgy.dao.UserDao">

    <select id="getUserList" resultType="top.mgy.pojo.User">
        select * from  mybatis.user;
    </select>

</mapper>
  • 测试
package top.mgy.dao.test;


import org.apache.ibatis.session.SqlSession;
import top.mgy.dao.UserMapper;
import top.mgy.pojo.User;
import top.mgy.utils.MybatisUtils;

import java.util.List;

public class UserDaoTest {

    public static void main(String[] args) {
        test();
    }
    public static void test(){
        //step1:获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //执行sql
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.getUserList();
        userList.forEach(System.out::println);

        sqlSession.close();
    }
}

CRUD

1、namespace

namespace 中的包名要和dao/mapper接口包名一致

2、select

  • id:就是对应的namespace中的方法名
  • resultType: SQL语句执行的返回值。

测试代码

package top.mgy.dao.test;


import org.apache.ibatis.session.SqlSession;
import top.mgy.dao.UserMapper;
import top.mgy.pojo.User;
import top.mgy.utils.MybatisUtils;

import java.util.List;

public class UserDaoTest {

    //step1:获取sqlSession对象
    static SqlSession  sqlSession = MybatisUtils.getSqlSession();
    public static void main(String[] args) {
        //test();
        //getUserById();
        //insertUser();
        //updataUser();
        deleteUser();
    }
    public static void test(){

        //执行sql
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.getUserList();
        userList.forEach(System.out::println);

        sqlSession.close();
    }

    //根据id获取用户
    public static void getUserById(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUsetById(1);
        System.out.println(user);
    }


    public static void insertUser(){
        /**
         * 增删改需要提交事务
         */
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int res = mapper.addUser(new User(4, "赵六", "79456"));
        if(res > 0){
            sqlSession.commit();
        }
        System.out.println(res);
    }

    public static void updataUser(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int res = mapper.updateUser(new User(4, "王琦", "456789123"));
        if(res >0){
            sqlSession.commit();
        }
        System.out.println(res);

    }

    public static void deleteUser(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int res = mapper.deleteUser(4);
        if(res>0){
            sqlSession.commit();
        }
        System.out.println(res);
    }
}

UserMapper

package top.mgy.dao;

import top.mgy.pojo.User;

import java.util.List;

public interface UserMapper {

    List<User> getUserList();

    User getUsetById(int id);

    int addUser(User user);

    int updateUser(User user);

    int deleteUser(int id);
}

userMapeer.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=绑定一个对应的Dao/Mapper接口 -->
<mapper namespace="top.mgy.dao.UserMapper">

    <select id="getUserList" resultType="top.mgy.pojo.User">
        select * from  mybatis.user;
    </select>

    <select id="getUsetById" resultType="top.mgy.pojo.User">
        select * from mybatis.user where id=#{id}
    </select>

    <!--对象中的属性可以直接取出-->
    <insert id="addUser" parameterType="top.mgy.pojo.User">
        insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
    </insert>

    <update id="updateUser" parameterType="top.mgy.pojo.User">
        update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id};
    </update>

    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id};
    </delete>

</mapper>

万能map

假设我们要修改一个100个字段的表中的一个字段,如果为了修改一个字段而创建一个对象,不值,可以使用map直接传值修改。

在传递多个参数的情况下,可以使用map

  • 接口
int updateUser2(Map<String,Object> map);
  • xml
sql中的参数就是map的key
<update id="updateUser2" parameterType="map">
        update mybatis.user set pwd=#{password} where id=#{id}
    </update>
  • test
 //通过map修改值
    public static void updateUser2(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String,Object> map = new HashMap<>();
        map.put("id",1);
        map.put("password","qqqwwwee");
        int res = mapper.updateUser2(map);
        if(res > 0){
            sqlSession.commit();
            System.out.println(res);
        }

模糊查询

//模糊查询
    public static void getUserLike(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userLike = mapper.getUserLike("%王%");
        userLike.forEach(System.out::println);
    }
<select id="getUserLike" resultType="top.mgy.pojo.User">
        select * from mybatis.user where name like #{value}
    </select>
List<User> getUserLike(String value);

配置解析

1、核心配置文件

  • mybatsi-config.xml

2、配置环境

mybatis可以配置成适应多环境的
不过要记住:尽管可以配置多个环境,但是每个SqlSessionFactory实例只能选择一种环境

Mybatis默认的事务管理器是JDBC,会配置多个运行环境。

3、属性

可以通过properties属性配置引用属性

  • 编写一个配置文件
    db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mp?useUnicode=true&charcaterEncoding=uft8&serverTimezone=UTC
username=root
password=root
  • 在核心配置文件中引入
 <!--引入外部配置文件-->
    <properties resource="db.properties"/>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

4、别名

  • 设置一个短的名字
  • 存在的意义是为了减少java类的完全限定名词
<!--配置别名-->
<!--配置类别名,适合少量pojo类-->
    <typeAliases>
        <typeAlias type="top.mgy.pojo.User" alias="User"/>
    </typeAliases>
    <!--配置包别名 在接口中可以使用 @Alias("User")注解配置DIY别名-->
    <typeAliases>
        <package name="top.mgy.pojo"/>
    </typeAliases>
    
  • UserMapper.xml中即可简写类名
<select id="getUserList" resultType="User">
        select * from  mybatis.user;
    </select>

设置(settings)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

设置名 描述 有效值 默认值
cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 true | false false
aggressiveLazyLoading 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。 true | false false (在 3.4.1 及之前的版本中默认为 true)
multipleResultSetsEnabled 是否允许单个语句返回多结果集(需要数据库驱动支持)。 true | false true
useColumnLabel 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 true | false true
useGeneratedKeys 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 true | false False
autoMappingBehavior 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 NONE, PARTIAL, FULL PARTIAL
autoMappingUnknownColumnBehavior 指定发现自动映射目标未知列(或未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARNFAILING: 映射失败 (抛出 SqlSessionException) NONE, WARNING, FAILING NONE
defaultExecutorType 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 任意正整数 未设置 (null)
defaultFetchSize 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 任意正整数 未设置 (null)
defaultResultSetType 指定语句默认的滚动策略。(新增于 3.5.2) FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置) 未设置 (null)
safeRowBoundsEnabled 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 true | false False
safeResultHandlerEnabled 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 true | false True
mapUnderscoreToCamelCase 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 true | false False
localCacheScope MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 SESSION | STATEMENT SESSION
jdbcTypeForNull 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 OTHER
lazyLoadTriggerMethods 指定对象的哪些方法触发一次延迟加载。 用逗号分隔的方法列表。 equals,clone,hashCode,toString
defaultScriptingLanguage 指定动态 SQL 生成使用的默认脚本语言。 一个类型别名或全限定类名。 org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler 指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5) 一个类型别名或全限定类名。 org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 true | false false
returnInstanceForEmptyRow 当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2) true | false false
logPrefix 指定 MyBatis 增加到日志名称的前缀。 任何字符串 未设置
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置
proxyFactory 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 以上)
vfsImpl 指定 VFS 的实现 自定义 VFS 的实现的类全限定名,以逗号分隔。 未设置
useActualParamName 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1) true | false true
configurationFactory 指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3) 一个类型别名或完全限定类名。
  • 一个配置完整的 settings 元素的示例如下:
<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

插件

  • mybatis Generator Core 代码生成插件
  • MyBatis Puus mybatis加强插件

6、映射器

MapperRegistry:注册绑定我们的Mapper配置文件

<mappers>
        <mapper resource="/top/mgy/dao/UserMapper.xml"/>
        <!--使用这种class的方式一定要确保UserMapper.xml和类所在包的包结构要一致才可以-->
        <mapper class="top.mgy.dao.UserMapper"/>
        <!--也可以使用包扫描,要确保xml文件和接口名称必须一致-->
        <package name="top.mgy.dao"/>
    </mappers>

7、什么周期和作用域

生命周期、和作用域,是至关重要的,因为错误的使用将会导致严重的并发问题

SqlSessionFactoryBuilder

  • 一旦创建了SqlSessionFactory,它就没用了
  • 所以需要放在局部变量

SqlSessionFactory

  • 可以想象为一个数据库连接池:
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或者重新创建另一个实例
  • 因此SqlSessionFactory的最佳作用域应该是应用作用域
  • 最简单的就是使用单例模式或者静态单例模式

SqlSession

  • 连接池的一个请求!
  • SqlSession 的实例不是线程安全的,因此不能被共享的,所以它的最佳作用域是请求或者方法内。
  • 用完之后就赶紧关了,避免资源浪费!

8、ResultMap

结果集映射。解决数据库中的字段和pojo中字段不一致问题

  • 数据库中字段
    image

  • pojo

@Alias("User1")
public class User1 {
    private int id;
    private String name;
    private String password;
}
 

xml

 <select id="getUsetById" resultType="User1">
        select * from mybatis.user where id=#{id}
    </select>
  • 测试出现问题

password 没有值

User1(id=1, name=张三, password=null)
  • 修改sql文件
<select id="getUsetById" resultType="User1">
        select id,name,pwd as password from mybatis.user where id=#{id}
    </select>
  • 可以查出来了

说明字段没有映射上

User1(id=1, name=张三, password=qqqwwwee)
  • 解决
    • sql起别名
    • 通过resultMap映射
<!--结果集映射 将pwd映射为password-->
    <resultMap id="User1Map" type="User1">
        <!--只需要映射不一致的字段即可-->
        <result property="password" column="pwd"/>
    </resultMap>

    <!--这里User1中的password属性和数据库中pwd字段不一致,要使用ResultMap映射-->
    <select id="getUsetById" resultMap="User1Map">
        select * from mybatis.user where id=#{id}
    </select>

这只是简单映射,但世界要这么简单就好了

更加复杂的映射

加入日志

  • mybatis-config.xml
 <!--配置日志-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

配置log4j

mybatis-config.xml

<!--配置日志-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
  • log4j.properties
log4j.rootLogger=DEBUG,console,file
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/mgy.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=【%p】【%d{yy-MM-dd}】【%c】%m%n
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=【%c】-%m%n

分页

  • 写sql实现
 private static void getUserByLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        Map<String,Integer> map = new HashMap<>();
        map.put("startIndex",0);
        map.put("PageSize",2);

        List<User> userByLimit = mapper.getUserByLimit(map);
        userByLimit.forEach(System.out::println);

        sqlSession.close();
    }
 <select id="getUserByLimit" parameterType="map" resultType="User">
        select * from mybatis.user limit #{startIndex},#{PageSize}
    </select>
 //分页
    List<User> getUserByLimit(Map<String,Integer> map);
  • 分页插件
    • PageHelper

使用注解开发

//开启自动提交事务
sqlSessionFactory.openSession(true);
  <!--绑定接口-->
    <mappers>
        <mapper class="mgy.dao.UserMapper"/>
    </mappers>
package mgy.dao;

import mgy.pojo.User;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface UserMapper {

    @Select("select * from user")
  List<User> getUsers();

}

-test


public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();

    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> users = mapper.getUsers();
    users.forEach(System.out::println);

    sqlSession.close();
}

多对一

-sql

CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');

CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

步骤

1、导入lombok
2、建立实体类 Teacher,Student
3、建立对应的Mapperjiek
4、建立接口对应的XML
5、在核心配置文件中绑定Mapper接口或文件
6、查询测试
  • 方式1(使用子查询)
  • 查询复杂所有学生及学生对应的老师
<select id="getStudent" resultMap="StudentTeacher">
       select * from student;
   </select>
   <resultMap id="StudentTeacher" type="Student">
       <result property="id" column="id"/>
       <result property="name" column="name"/>
       <!--复杂属性,需要单独处理 对象使用:association 集合使用Collection-->
       <!--javaType表示复杂属性的类型   select可以理解为一个子查询,根据 pid=id去查询老师信息-->
       <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
   </resultMap>
   
   <select id="getTeacher" resultType="Teacher">
       select * from teacher where id = #{id}
   </select>
  • 方式2(按照结果查询)
   <select id="getStudent2" resultMap="StudentTeacher2">
       select s.id sid,s.name sname,t.name tname from student s left join teacher t on s.tid = t.id
   </select>
   <resultMap id="StudentTeacher2" type="Student">
       <result property="id" column="sid"/>
       <result property="name" column="sname"/>
       <!--这里应该Teacher是一个复杂类型,所以需要通过 association 映射里面的值-->
       <association property="teacher" javaType="Teacher">
           <result property="name" column="tname"/>
       </association>
   </resultMap>
 private static void getStudent2(){
       SqlSession sqlSession = MybatisUtils.getSqlSession();

       StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
       List<Student> student2 = mapper.getStudent2();
       student2.forEach(System.out::println);

       sqlSession.close();
   }

一对多查询

  • pojo

student

package top.mgy.pojo;

import lombok.Data;

@Data
public class Student1 {

    private int id;
    private String name;
    //学生关联老师
    private int tid;
}

teacher

package top.mgy.pojo;

import lombok.Data;

import java.util.List;

/**
 * 一对多 一个老师对应多个学生
 */
@Data
public class Teacher1 {

    private int id;
    private String name;
    private List<Student1> students;

}

xml sql 按结果查询

<select id="getTeacher2" resultMap="TeacherStudent">
        select s.id sid,s.name sname,t.id tid,t.name tname 
        from student s left join teacher t 
        on s.tid = t.id 
        where t.id=#{id}
    </select>
    
    <resultMap id="TeacherStudent" type="Teacher1">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <!--list需要使用collection   , ofType和javaType差不多,只不过ofType是取泛型-->
        <collection property="students" ofType="Student1">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>

查询结果

Teacher1(id=1, name=秦老师, students=[Student1(id=1, name=小明, tid=1), Student1(id=2, name=小红, tid=1), Student1(id=3, name=小张, tid=1), Student1(id=4, name=小李, tid=1), Student1(id=5, name=小王, tid=1)])

动态SQL

动态SQL就是指:根据不同条件生成不用的SQL语句

  • if
  • choose(when,otherwise)
  • foreach

环境

  • sql
CREATE TABLE `blog`(
  `id` VARCHAR(50) NOT NULL COMMENT '博客id',
  `title` VARCHAR(100) NOT NULL COMMENT '博客标题',
  `author` VARCHAR(30) NOT NULL COMMENT '博客作者',
  `create_time` DATETIME NOT NULL COMMENT '创建时间',
  `views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8
  • 实体类
package top.mgy.pojo;

import lombok.Data;

import java.util.Date;

@Data
public class Blog {
    private int id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

  • IDUtils
package top.mgy.utils;

import java.util.UUID;

@SuppressWarnings("all") //抑制警告
public class IDUtils {

    public static String getId(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }

    public static void main(String[] args) {
        System.out.println(getId());
    }
}

IF

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="top.mgy.dao.BlogMapper">
    <insert id="addBlok" parameterType="Blog">
        insert into mybatis.blog(id, title, author, create_time, views)
        values (#{id}, #{title}, #{author}, #{createTime}, #{views})
    </insert>

    <select id="getBlogIf" parameterType="map" resultType="Blog">
        select * from mybatis.blog where 1=1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </select>
</mapper>
  • 添加数据
private static void addBlog() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        Blog blog = new Blog();
        blog.setId(IDUtils.getId());
        blog.setTitle("Mybatis如此简单");
        blog.setAuthor("Mgy");
        blog.setCreateTime(new Date());
        blog.setViews(9999);
        mapper.addBlok(blog);


        blog.setId(IDUtils.getId());
        blog.setTitle("Spring如此简单");
        blog.setCreateTime(new Date());
        mapper.addBlok(blog);


        blog.setId(IDUtils.getId());
        blog.setTitle("Spring Boot如此简单");
        blog.setCreateTime(new Date());
        mapper.addBlok(blog);

        sqlSession.close();
    }
  • 查询

可根据titleauthor是否传入动态查询

 SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Map map = new HashMap();
        //传入title,就按照title查询
        map.put("title","Mybatis如此简单");
        List<Blog> blogIf = mapper.getBlogIf(map);
        blogIf.forEach(System.out::println);
        sqlSession.close();
  • 结果
Blog(id=e09e92980a51496c81da1f929913e891, title=Mybatis如此简单, author=Mgy, createTime=Fri Apr 17 18:15:51 CST 2020, views=9999)

where

可以使用where更好的处理 where后面的查询条件,
where的查询条件中,如果是所有添加都不符合,会自动去掉where,如果第一个条件不符合,会自动去掉后面变为第一个条件的 and 或者 or 关键字。保证sql的拼接正确。

 <select id="getBlogIf" parameterType="map" resultType="Blog">
        select * from mybatis.blog
        <where>
          <if test="title != null">
            title = #{title}
          </if>
          <if test="author != null">
              and author = #{author}
          </if>
        </where>
    </select>
  • choose
    image

  • set
    image

  • sql片段
    image

  • 注意

  • 最好基于单表来定义SQL片段

  • 不要存在where标签

  • foreach
    image

posted @ 2020-12-31 10:52  告一段落  阅读(103)  评论(0编辑  收藏  举报