zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    第一次来博客园,不写技术
    asp.net跳转页面的三种方法比较
    那年五月
    在GridView里使用单选按钮,RadioButton/Radio
    常用网页嵌入播放器代码精解收集
    HTML 嵌入视频
    代码规范
    C:\WINDOWS\system32\wmp.dll”受到“Windows 系统文件保护”。
    window.pageyoffset和document.body.scrollTop
    网页制作中段落缩进的5种解决方法
  • 原文地址:https://www.cnblogs.com/maguangyi/p/14215065.html
Copyright © 2011-2022 走看看