zoukankan      html  css  js  c++  java
  • MyBatis 教程 ——检视阅读

    MyBatis 教程 ——检视阅读

    准备

    官网文档-中文

    教程地址yiibai,质量很差

    教程地址w3cschool,纯理论,还不如直接看官网文档

    教程地址Mybatis框架入门教程,Oracle

    Maven官网

    maven pom依赖搜索

    回答

    1. 这个教程大体在讲什么?
    2. 教程细部说了什么?
    3. 是否同意教程的知识和观点,同意程度?
    4. 该教程为了带来了什么?

    前言

    MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录。

    每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得。

    用xml文件构建SqlSessionFactory实例是非常简单的事情。推荐在这个配置中使用类路径资源(classpath resource),但你可以使用任何Reader实例,包括用文件路径或file://开头的url创建的实例。MyBatis有一个实用类----Resources,它有很多方法,可以方便地从类路径及其它位置加载资源。
    

    MyBatis 最强大的特性之一就是它的动态语句功能。如果您以前有使用JDBC或者类似框架的经历,您就会明白把SQL语句条件连接在一起是多么的痛苦,要确保不能忘记空格或者不要在columns列后面省略一个逗号等。

    MyBatis环境配置搭建项目

    上来直接构建一个经典的maven web项目。

    前提:

    #数据库、表
    CREATE DATABASE hello_mybatis;
    
    USE hello_mybatis;
    
    CREATE TABLE `t_user` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` varchar(64) NOT NULL  COMMENT '姓名',
      `dept` varchar(254) NOT NULL  COMMENT '部门',
      `phone` varchar(16) NOT NULL COMMENT '电话',
      `height` decimal(10,2) DEFAULT NULL COMMENT '身高',
    	`create_emp` bigint(20) NOT NULL COMMENT '创建人',
      `create_time` datetime DEFAULT NULL COMMENT '创建时间',
      `modify_emp` bigint(20) DEFAULT NULL COMMENT '修改人',
      `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
      PRIMARY KEY (`id`),
      KEY `idx_name` (`name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表';
    
    INSERT INTO `hello_mybatis`.`t_user` (`name`, `dept`, `phone`, `height`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES
     ( '大青山', 'amy empire', '18956563229', '1.85', '1', '2020-03-31 14:17:35', '1', '2020-03-31 14:17:47');
    
    INSERT INTO `hello_mybatis`.`t_user` (`name`, `dept`, `phone`, `height`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES
     ( '池寒枫', 'amy empire', '22056545', '1.83', '1', '2020-03-31 14:17:35', '1', '2020-03-31 14:17:47');
    

    代码示例:

    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>
        <typeAliases>
            <typeAlias alias="User" type="com.self.bean.User" />
        </typeAliases>
        <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/hello_mybatis" />
                    <property name="username" value="root" />
                    <property name="password" value="123456" />
                </dataSource>
            </environment>
        </environments>
    
        <mappers>
            <mapper resource="com/self/dao/UserMapper.xml" />
        </mappers>
    </configuration>
    

    注意: 对应的是UserMapper.xml在classpath下的地址,后缀.xml要带上(下面的报错就是文件名没有后缀),路径地址要对,否则会报错。

    Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/self/dao/UserMapper
    

    UserMapper.xml

    CRUD 的sql在各个对应的Mapper 映射文件上写。

    <?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.self.dao.UserMapper">
        <select id="getUserById" parameterType="int" resultType="User">
    		select * from `t_user` where id = #{id}
        </select>
    </mapper>
    

    bean,数据库的映射对象实体类。

    public class User {
        /**
         * id
         */
        private int id;
        /**
         * 名字
         */
        private String name;
        /**
         * 部门,帝国
         */
        private String dept;
        /**
         * 联系号码
         */
        private String phone;
        /**
         * 身高
         */
        private BigDecimal height;
        /**
         * 创建人
         */
        private Long createEmp;
        /**
         * 创建时间
         */
        private String createTime;
        /**
         * 修改人
         */
        private Long modifyEmp;
        /**
         * 修改时间
         */
        private String modifyTime;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    //其他省略
    }
    

    main方法。

    public class HelloTest {
        private static SqlSessionFactory sqlSessionFactory;
        private static Reader reader;
    
        static {
            try {
                reader = Resources.getResourceAsReader("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static SqlSessionFactory getSessionFactory(){
            return sqlSessionFactory;
        }
        
        public static void main(String[] args) {
            SqlSession sqlSession = getSessionFactory().openSession();
            try {
                 //我们通过调用UserMapper.xml的namespace + id(方法名)来完成数据库访问
                User user = (User)sqlSession.selectOne("com.self.dao.UserMapper.getUserById", 1);
                System.out.println(JSON.toJSONString(user));
            } finally {
                sqlSession.close();
            }
        }
    }
    

    输出:

    {"dept":"amy empire","height":1.75,"id":1,"name":"艾米","phone":"18956563228"}
    

    配置解释:

    1. 配置文件 mybatis-config.xml 是 mybatis 用来建立 sessionFactory,里面主要包含了数据库连接相关内容,还有 java 类所对应的别名,比如: 这个别名非常重要,在具体的类的映射中,比如:UserMapper.xml 中 resultType 就是对应这个。
    2. mybatis-config.xml 里面 的是包含要映射的类(UserMapper.java)的 xml 配置文件。
    3. 在UserMapper.xml 文件里面主要是定义各种 SQL 语句,以及这些语句的参数,以及要返回的类型等等。

    Mybatis接口注解 (项目中一般不使用)

    示例:

    创建DAO接口

    package com.self.dao;
    
    import com.self.bean.User;
    import org.apache.ibatis.annotations.Select;
    
    public interface UserMapper {
    
        @Select("SELECT * FROM t_user where name =#{name}")
        public User getUserByName(String name);
    }
    

    mybatis-config.xml 配置文件不需要配置mappers,转而在sqlSessionFactory.getConfiguration().addMapper(IUser.class);里添加。

    <?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>
        <typeAliases>
            <typeAlias alias="User" type="com.self.bean.User" />
        </typeAliases>
        <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/hello_mybatis" />
                    <property name="username" value="root" />
                    <property name="password" value="123456" />
                </dataSource>
            </environment>
        </environments>
    
        <!--<mappers>-->
            <!--<mapper resource="com/self/dao/UserMapper.xml" />-->
        <!--</mappers>-->
    </configuration>
    

    User 实体类不变。

    测试类

    public class HelloTest {
        private static SqlSessionFactory sqlSessionFactory;
        private static Reader reader;
    
        static {
            try {
                reader = Resources.getResourceAsReader("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
                   //在sqlSessionFactory中添加Mapper
                sqlSessionFactory.getConfiguration().addMapper(UserMapper.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static SqlSessionFactory getSessionFactory(){
            return sqlSessionFactory;
        }
    
        public static void main(String[] args) {
            SqlSession sqlSession = getSessionFactory().openSession();
            try {
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                User user = userMapper.getUserByName("大青山");
                System.out.println(JSON.toJSONString(user));
            } finally {
                sqlSession.close();
            }
        }
    }
    

    Mybatis增删改查(CURD)

    示例:

    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>
        <typeAliases>
            <typeAlias alias="User" type="com.self.bean.User" />
        </typeAliases>
        <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/hello_mybatis" />
                    <property name="username" value="root" />
                    <property name="password" value="123456" />
                </dataSource>
            </environment>
        </environments>
    
        <mappers>
            <mapper resource="com/self/dao/UserMapper.xml" />
        </mappers>
    </configuration>
    

    User 实体类不变。

    dao层接口

    public interface UserMapper {
    
        public User getUserById(Integer id);
    
        public List<User> getUsers();
    
        public void insert(User user);
    
        public void update(User user);
    
        public void deleteById(Integer id);
    }
    

    Mapper 映射文件 : srcmain esourcescomselfdaoUserMapper.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="com.self.dao.UserMapper">
        <select id="getUserById" parameterType="int" resultType="User">
    		select * from `t_user` where id = #{id}
        </select>
    
        <select id="getUsers" resultType="User">
            select * from `t_user` where 1 = 1
        </select>
    
        <insert id="insert" parameterType="User">
            insert into t_user(`name`, `dept`, `phone`, `height`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES
            (#{name},#{dept},#{phone},#{height},#{createEmp},#{createTime},#{modifyEmp},#{modifyTime})
        </insert>
        <delete id="deleteById" parameterType="Integer">
            delete from t_user where id = #{id}
        </delete>
        <update id="update" parameterType="User">
            update t_user
            <set>
                <if test="name != null">
                    name = #{name},
                </if>
                <if test="dept != null">
                    dept = #{dept},
                </if>
                <if test="phone != null">
                    phone = #{phone},
                </if>
                <if test="height != null">
                    height = #{height},
                </if>
                <if test="modifyEmp != null">
                    modify_emp = #{modifyEmp},
                </if>
                <if test="modifyTime != null">
                    modify_time = #{modifyTime}
                </if>
            </set>
            where id = #{id}
        </update>
    </mapper>
    

    测试类

    package com.self;
    
    import com.alibaba.fastjson.JSON;
    import com.self.bean.User;
    import com.self.dao.UserMapper;
    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.IOException;
    import java.io.Reader;
    import java.math.BigDecimal;
    import java.util.Date;
    import java.util.List;
    
    
    public class HelloTest {
        private static SqlSessionFactory sqlSessionFactory;
        private static Reader reader;
    
        static {
            try {
                reader = Resources.getResourceAsReader("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
                //在sqlSessionFactory中添加Mapper
                //sqlSessionFactory.getConfiguration().addMapper(UserMapper.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static SqlSessionFactory getSessionFactory(){
            return sqlSessionFactory;
        }
    
        public static void main(String[] args) {
            SqlSession sqlSession = getSessionFactory().openSession();
            try {
                //我们通过调用UserMapper.xml的namespace + id(方法名)来完成数据库访问
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                User user = new User();
                user.setCreateEmp(3L);
                user.setCreateTime(new Date());
                user.setDept("矮人王国");
                user.setHeight(new BigDecimal("1.53"));
                user.setModifyEmp(3L);
                user.setModifyTime(new Date());
                user.setPhone("852-253521");
                user.setName("霍恩斯");
                userMapper.insert(user);
    
                User user1 = new User();
                user1.setCreateEmp(3L);
                user1.setCreateTime(new Date());
                user1.setDept("矮人王国");
                user1.setHeight(new BigDecimal("1.53"));
                user1.setModifyEmp(3L);
                user1.setModifyTime(new Date());
                user1.setPhone("852-253521");
                user1.setName("霍恩斯-克隆");
                userMapper.insert(user1);
                sqlSession.commit();
                System.out.println("--------------------insert---------------------");
    
                User user2 = userMapper.getUserById(4);
                System.out.println("-----getUserById----"+JSON.toJSONString(user2));
    
                User updateUser = new User();
                updateUser.setDept("森林矮人王国");
                updateUser.setHeight(new BigDecimal("1.56"));
                updateUser.setModifyEmp(6L);
                updateUser.setModifyTime(new Date());
                updateUser.setPhone("852-253521");
                updateUser.setName("霍恩斯");
                updateUser.setId(user2.getId());
                userMapper.update(updateUser);
                sqlSession.commit();
                System.out.println("--------------------update---------------------");
    
                List<User> users = userMapper.getUsers();
                System.out.println("----before delete-----"+JSON.toJSONString(users));
                userMapper.deleteById(5);
                sqlSession.commit();
                System.out.println("--------------------deleteById---------------------");
    
                List<User> afterUsers = userMapper.getUsers();
                System.out.println("----before delete-----"+JSON.toJSONString(afterUsers));
            } finally {
                sqlSession.close();
            }
        }
    }
    

    输出:

    --------------------insert---------------------
    -----getUserById----{"dept":"矮人王国","height":1.53,"id":4,"name":"霍恩斯","phone":"852-253521"}
    --------------------update---------------------
    ----before delete-----[{"dept":"amy empire","height":1.75,"id":1,"name":"艾米","phone":"18956563228"},{"dept":"amy empire","height":1.85,"id":2,"name":"大青山","phone":"18956563229"},{"dept":"amy empire","height":1.83,"id":3,"name":"池寒枫","phone":"22056545"},{"dept":"森林矮人王国","height":1.56,"id":4,"name":"霍恩斯","phone":"852-253521"},{"dept":"矮人王国","height":1.53,"id":5,"name":"霍恩斯-克隆","phone":"852-253521"}]
    --------------------deleteById---------------------
    ----before delete-----[{"dept":"amy empire","height":1.75,"id":1,"name":"艾米","phone":"18956563228"},{"dept":"amy empire","height":1.85,"id":2,"name":"大青山","phone":"18956563229"},{"dept":"amy empire","height":1.83,"id":3,"name":"池寒枫","phone":"22056545"},{"dept":"森林矮人王国","height":1.56,"id":4,"name":"霍恩斯","phone":"852-253521"}]
    

    注意:在增加,更改,删除的时候需要调用 session.commit() 来提交事务,这样才会真正对数据库进行操作提交保存,否则操作没有提交到数据中。

    注意:

    1、如果在mybatis-config.xml没有配置mapper的xml文件就会报下面的UserMapper is not known to the MapperRegistry.

    Exception in thread "main" org.apache.ibatis.binding.BindingException: Type interface com.self.dao.UserMapper is not known to the MapperRegistry.
    	at org.apache.ibatis.binding.MapperRegistry.getMapper
    

    2、如果插入的数据与字段不匹配个数会报Column count doesn't match value count at row 1。

    ### SQL: insert into t_user(`name`, `dept`, `phone`, `height`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES         (?,?,?,?,?,?,?,?,?)
    ### Cause: java.sql.SQLException: Column count doesn't match value count at row 1
    

    Mybatis表关联一对多

    准备:

    CREATE TABLE `t_weibo` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
      `user_id` int(10) unsigned NOT NULL COMMENT '用户id',
      `title` varchar(254) NOT NULL COMMENT '主题',
      `content` text DEFAULT NULL COMMENT '内容',
      `create_emp` bigint(20) NOT NULL COMMENT '创建人',
      `create_time` datetime DEFAULT NULL COMMENT '创建时间',
      `modify_emp` bigint(20) DEFAULT NULL COMMENT '修改人',
      `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
      PRIMARY KEY (`id`),
      KEY `idx_user_id` (`user_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT= 1000 DEFAULT CHARSET=utf8 COMMENT='微博帖子表';
    
    INSERT INTO `hello_mybatis`.`t_weibo` ( `user_id`, `title`, `content`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) 
    VALUES ( '4', '霍恩斯描述', '由于矮人种族的原因,他无法成为龙骑士,但这并不影响他在小佣兵团以及整个人神大战中快速成为超级巨星,擅长谋略尤擅兵法让他成为矮人的异类。', '2', '2020-04-01 13:47:24', '2', '2020-04-01 13:47:31');
    
    INSERT INTO `hello_mybatis`.`t_weibo` ( `user_id`, `title`, `content`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) 
    VALUES ( '4', '霍恩斯与莹', '艾米、大青山、霍恩斯、池傲天、沙若等佣兵团骨干可以逃脱,那些培养了2年多的人才必然全军覆没。', '2', '2020-04-01 13:47:24', '2', '2020-04-01 13:47:31');
    
    INSERT INTO `hello_mybatis`.`t_weibo` ( `user_id`, `title`, `content`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES
     ( '2', '大青山描述', '史料记载中第一个神圣巨龙使骑士,在所有的文明中,他都是传统骑士准则的典范,正直、善良、忠诚、守信、怜悯等一切人类美德的拥有者。人龙神三人组合中的一人。在神界受到龙神以黄金凤的胁迫,毅然解除与冰系神圣巨龙使泰穆格尔赛的龙骑士契约,解除龙神的威胁,后与光明神同归于尽。', '2', '2020-04-01 13:47:24', '2', '2020-04-01 13:47:31');
    

    实例:

    public class User {
        /**
         * id
         */
        private int id;
        /**
         * 名字
         */
        private String name;
        /**
         * 部门,帝国
         */
        private String dept;
        /**
         * 联系号码
         */
        private String phone;
        /**
         * 身高
         */
        private BigDecimal height;
    
        private List<Weibo> weibos;
        /**
         * 创建人
         */
        private Long createEmp;
        /**
         * 创建时间
         */
        private Date createTime;
        /**
         * 修改人
         */
        private Long modifyEmp;
        /**
         * 修改时间
         */
        private Date modifyTime;
    
        public List<Weibo> getWeibos() {
            return weibos;
        }
    
        public void setWeibos(List<Weibo> weibos) {
            this.weibos = weibos;
        }
        //其他省略
       }
    
    public class Weibo {
    
        /**
         * id
         */
        private int id;
        /**
         * 主题
         */
        private String title;
        /**
         * 内容
         */
        private String content;
        /**
         * 用户信息
         */
        private User user;
        /**
         * 创建人
         */
        private Long createEmp;
        /**
         * 创建时间
         */
        private Date createTime;
        /**
         * 修改人
         */
        private Long modifyEmp;
        /**
         * 修改时间
         */
        private Date modifyTime;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    

    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>
        <typeAliases>
            <typeAlias alias="User" type="com.self.bean.User" />
            <typeAlias type="com.self.bean.Weibo" alias="Weibo"/>
        </typeAliases>
        <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/hello_mybatis" />
                    <property name="username" value="root" />
                    <property name="password" value="123456" />
                </dataSource>
            </environment>
        </environments>
    
        <mappers>
            <mapper resource="com/self/dao/UserMapper.xml" />
        </mappers>
    </configuration>
    

    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="com.self.dao.UserMapper">
        <resultMap id="userMap" type="User">
            <result property="id" column="user_id"/>
            <result property="name" column="name"/>
            <result property="dept" column="dept"/>
            <result property="phone" column="phone"/>
            <collection property="weibos" ofType="com.self.bean.Weibo" column="user_id">
                <!--<id property="id" column="t_weibo.id" javaType="int" jdbcType="INTEGER"  />-->
                <!--不加表别名或者表名来区分id的话会导致查询不出多条数据-->
                <id property="id" column="p.id" javaType="int" jdbcType="INTEGER"  />
                <result property="title" column="title" javaType="string" jdbcType="VARCHAR"/>
                <result property="content" column="content" javaType="string" jdbcType="VARCHAR"/>
            </collection>
        </resultMap>
        <select id="getUserInfoById" resultMap="userMap" parameterType="int">
            <!--    SELECT u.*,p.*
                FROM t_user u, t_weibo p
                WHERE u.id = p.user_id AND u.id=#{id}-->
          SELECT u.*,p.*
          FROM t_user u
           inner join t_weibo p on u.id = p.user_id
          WHERE  u.id=#{id}
      </select>
    </mapper>
    
    package com.self;
    
    import com.alibaba.fastjson.JSON;
    import com.self.bean.User;
    import com.self.dao.UserMapper;
    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.IOException;
    import java.io.Reader;
    import java.math.BigDecimal;
    import java.util.Date;
    import java.util.List;
    
    /**
     * Copyright (C), 2015-2020, UCAR.INC
     * ClassName: HelloTest
     * Author:   Rongfeng.Lai
     * Date:     2020/3/31 14:42
     * Description:
     * History:
     * <author>          <time>          <version>          <desc>
     * Rongfeng.Lai      2020/3/31          v1.1.0             描述
     */
    public class HelloTest {
        private static SqlSessionFactory sqlSessionFactory;
        private static Reader reader;
    
        static {
            try {
                reader = Resources.getResourceAsReader("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
                //在sqlSessionFactory中添加Mapper
                //sqlSessionFactory.getConfiguration().addMapper(UserMapper.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static SqlSessionFactory getSessionFactory(){
            return sqlSessionFactory;
        }
    
        public static void main(String[] args) {
            SqlSession sqlSession = getSessionFactory().openSession();
            try {
                User user = sqlSession.selectOne("com.self.dao.UserMapper.getUserInfoById", 4);
                System.out.println("---------"+JSON.toJSONString(user));
            } finally {
                sqlSession.close();
            }
        }
    }
    

    输出:

    ---------{"dept":"森林矮人王国","id":4,"name":"霍恩斯","phone":"852-253521","weibos":[{"content":"由于矮人种族的原因,他无法成为龙骑士,但这并不影响他在小佣兵团以及整个人神大战中快速成为超级巨星,擅长谋略尤擅兵法让他成为矮人的异类。","id":4,"title":"霍恩斯描述"}]}
    

    当配置resultMap时jdbcType="TEXT"会报错,要配置成jdbcType="VARCHAR"。

    <result property="content" column="content" javaType="string" jdbcType="TEXT"/>
    报错:
    Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'com/self/dao/UserMapper.xml'. Cause: org.apache.ibatis.builder.BuilderException: Error resolving JdbcType. Cause: java.lang.IllegalArgumentException: No enum constant org.apache.ibatis.type.JdbcType.TEXT
    

    Mybatis表关联多对一

    实例:

    实体类bean不变

    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">
        <resultMap id="weiboMap" type="Weibo">
            <result property="id" column="id"/>
            <result property="title" column="title"/>
            <result property="content" column="content"/>
            <association property="user" javaType="User">
                <id property="id" column="user_id"/>
                <result property="name" column="name"/>
                <result property="dept" column="dept"/>
                <result property="mobile" column="mobile"/>
            </association>
        </resultMap>
        <select id="getWeiboInfoById" resultMap="weiboMap" parameterType="int">
            SELECT u.*,w.*
            FROM t_user u
            inner join t_weibo w on u.id = w.user_id
            WHERE  w.id= #{id}
        </select>
    </mapper>
    

    测试类

      Weibo weibo = sqlSession.selectOne("com.self.dao.UserMapper.getWeiboInfoById", 1000);
                System.out.println("---------"+JSON.toJSONString(weibo));
    

    输出:

    ---------{"content":"史料记载中第一个神圣巨龙使骑士,在所有的文明中,他都是传统骑士准则的典范,正直、善良、忠诚、守信、怜悯等一切人类美德的拥有者。人龙神三人组合中的一人。在神界受到龙神以黄金凤的胁迫,毅然解除与冰系神圣巨龙使泰穆格尔赛的龙骑士契约,解除龙神的威胁,后与光明神同归于尽。","id":2,"title":"大青山描述","user":{"dept":"amy empire","id":2,"name":"大青山"}}
    

    Mybatis 多对多

    mybatis3.0 添加了association和collection标签专门用于对多个相关实体类数据进行级联查询,但仍不支持多个相关实体类数据的级联保存和级联删除操作。因此在进行实体类多对多映射表设计时,需要专门建立一个关联对象类对相关实体类的关联关系进行描述(映射表 user_side )。

    多对多关系本质上还是一对多关系的延伸,各自是一对多关系的联系,因此变成了多对多的关系,在对单个数据处理时还是一对多关系的处理。

    前提准备:

    CREATE TABLE `t_side` (
      `side_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
      `side_name` varchar(254) NOT NULL COMMENT '势力名称',
      `create_emp` bigint(20) NOT NULL COMMENT '创建人',
      `create_time` datetime DEFAULT NULL COMMENT '创建时间',
      `modify_emp` bigint(20) DEFAULT NULL COMMENT '修改人',
      `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
      PRIMARY KEY (`side_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8 COMMENT='所属势力表';
    
    INSERT INTO `hello_mybatis`.`t_side` ( `side_name`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES 
    ('艾米帝国', '10', '2020-04-01 16:36:25', '10', '2020-04-01 16:36:28');
    
    INSERT INTO `hello_mybatis`.`t_side` ( `side_name`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES 
    ('哈米尔王国', '10', '2020-04-01 16:36:25', '10', '2020-04-01 16:36:28');
    
    INSERT INTO `hello_mybatis`.`t_side` ( `side_name`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES 
    ('恶魔岛', '10', '2020-04-01 16:36:25', '10', '2020-04-01 16:36:28');
    
    INSERT INTO `hello_mybatis`.`t_side` ( `side_name`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES 
    ('精灵王国', '10', '2020-04-01 16:36:25', '10', '2020-04-01 16:36:28');
    
    CREATE TABLE `t_user_side` (
      `user_id` int(10) unsigned NOT NULL COMMENT '用户id' ,
      `side_id` int(10) unsigned NOT NULL COMMENT '所属势力id'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT ='用户势力映射表';
    
    INSERT INTO `hello_mybatis`.`t_user_side` (`user_id`, `side_id`) VALUES ('1', '100');
    INSERT INTO `hello_mybatis`.`t_user_side` (`user_id`, `side_id`) VALUES ('1', '101');
    INSERT INTO `hello_mybatis`.`t_user_side` (`user_id`, `side_id`) VALUES ('1', '103');
    INSERT INTO `hello_mybatis`.`t_user_side` (`user_id`, `side_id`) VALUES ('3', '100');
    INSERT INTO `hello_mybatis`.`t_user_side` (`user_id`, `side_id`) VALUES ('2', '100');
    
    sql错误修改
    
    ALTER TABLE t_user_group RENAME t_user_side;
    
    ALTER TABLE t_user_side CHANGE  group_id side_id int(10) unsigned NOT NULL COMMENT '所属势力id';
    

    实例:

    bean对象

    public class User {
    
        /**
         * 成员所属势力群
         */
        private List<Side> sides;
        /**
         * id
         */
        private int id;
        /**
         * 名字
         */
        private String name;
        /**
         * 部门,帝国
         */
        private String dept;
        /**
         * 联系号码
         */
        private String phone;
        /**
         * 身高
         */
        private BigDecimal height;
    
        //private List<Weibo> weibos;
        /**
         * 创建人
         */
        private Long createEmp;
        /**
         * 创建时间
         */
        private Date createTime;
        /**
         * 修改人
         */
        private Long modifyEmp;
        /**
         * 修改时间
         */
        private Date modifyTime;
        }
    
    public class Side {
    
        /**
         * 所属势力下成员
         */
        private List<User> users;
        /**
         * 所属势力id
         */
        private int sideId;
        /**
         * 所属势力名称
         */
        private String sideName;
        /**
         * 创建人
         */
        private Long createEmp;
        /**
         * 创建时间
         */
        private Date createTime;
        /**
         * 修改人
         */
        private Long modifyEmp;
        /**
         * 修改时间
         */
        private Date modifyTime;
        }
    
    public class UserSide {
    
        /**
         * 用户id
         */
        private int userId;
    
        /**
         * 势力id
         */
        private int sideId;
        }
    

    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>
        <typeAliases>
            <typeAlias alias="User" type="com.self.bean.User" />
            <typeAlias type="com.self.bean.Side" alias="Side"/>
            <typeAlias type="com.self.bean.UserSide" alias="UserSide"/>
        </typeAliases>
        <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/hello_mybatis" />
                    <property name="username" value="root" />
                    <property name="password" value="123456" />
                </dataSource>
            </environment>
        </environments>
    
        <mappers>
            <mapper resource="com/self/dao/UserMapper.xml" />
            <mapper resource="com/self/dao/SideMapper.xml"/>
            <mapper resource="com/self/dao/UserSideMapper.xml"/>
        </mappers>
    </configuration>
    

    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="com.self.dao.UserMapper">
        <resultMap id="userMap" type="User">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="phone" column="phone"/>
            <collection property="sides" column="user_id" select="com.self.dao.UserSideMapper.getSidesByUserId"/>
        </resultMap>
        <select id="getUserById" parameterType="int" resultMap="userMap">
          select * from `t_user` where id = #{id}
        </select>
    </mapper>
    

    SideMapper.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="com.self.dao.SideMapper">
        <resultMap id="sideMap" type="Side">
            <result property="sideId" column="side_id"/>
            <result property="sideName" column="side_name"/>
            <collection property="users" column="side_id" select="com.self.dao.UserSideMapper.getUsersBySideId"/>
        </resultMap>
    
        <select id="getSideById" parameterType="int" resultMap="sideMap">
          select * from `t_side` where side_id = #{sideId}
        </select>
    
        <insert id="insert" parameterType="Side">
            insert into t_side(`side_name`, `create_emp`, `create_time`, `modify_emp`, `modify_time`) VALUES
            (#{sideName},#{createEmp},#{createTime},#{modifyEmp},#{modifyTime})
        </insert>
    </mapper>
    

    UserSideMapper.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="com.self.dao.UserSideMapper">
        <resultMap id="userSideMap" type="UserSide">
            <result property="userId" column="user_id"/>
            <result property="sideId" column="side_id"/>
        </resultMap>
        <resultMap id="userMap" type="User">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="phone" column="phone"/>
        </resultMap>
        <resultMap id="sideMap" type="Side">
            <result property="sideId" column="side_id"/>
            <result property="sideName" column="side_name"/>
            <collection property="users" column="side_id" select="com.self.dao.UserSideMapper.getUsersBySideId"/>
        </resultMap>
        <select id="getSidesByUserId" resultMap="sideMap" parameterType="int">
            select s.* , us.user_id from t_side s inner join t_user_side us on s.side_id = us.side_id
            where us.user_id = #{userId}
        </select>
    
        <select id="getUsersBySideId" resultMap="userMap" parameterType="int">
            select u.* , us.side_id from t_user u inner join t_user_side us on u.id = us.user_id
            where us.side_id = #{sideId}
        </select>
    
        <insert id="insert" parameterType="UserSide">
            INSERT INTO t_user_side (`user_id`, `group_id`) VALUES (#{userId},#{sideId})
        </insert>
    </mapper>
    
    //测试类代码
    UserSideMapper us = sqlSession.getMapper(UserSideMapper.class);
    List<Side> sides = us.getSidesByUserId(1);
    StringBuilder sb = new StringBuilder();
    for (Side side : sides) {
        sb.append(side.getSideName()+",  ");
    }
    System.out.println("----------该成员所属势力-------------"+sb);
    List<User> users = us.getUsersBySideId(100);
    StringBuilder sb2 = new StringBuilder();
    for (User user : users) {
        sb2.append(user.getName() + ",   ");
    }
    System.out.println("----------该势力拥有的成员-------------"+sb2);
    

    输出:

    ----------该成员所属势力-------------艾米帝国,  哈米尔王国,  精灵王国,  
    ----------该势力拥有的成员-------------艾米,   池寒枫,   大青山, 
    

    报错:

    1、Cannot find class: userMap 原因:

    Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'com/self/dao/UserMapper.xml'. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'userMap'.  Cause: java.lang.ClassNotFoundException: Cannot find class: userMap
    
    
    
      <select id="getUserById" parameterType="int" resultMap="userMap">
    select * from `t_user` where id = #{id}
      </select>
       <!--   自定义的bean实例类型要指定resultMap,resultType普通bean用的-->
      <select id="getUserById" parameterType="int" resultType="userMap">
      select * from `t_user` where id = #{id}
      </select> 
    

    Mybatis与Spring集成

    框架搭建的核心就是配置文件。

    实例:

    pom.xml依赖

    <dependencies>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
      </dependency>
      <!--=================mybatis框架依赖===============-->
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
      </dependency>
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.31</version>
      </dependency>
      <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>RELEASE</version>
        <scope>compile</scope>
      </dependency>
      <!--=================mybatis框架依赖===============-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.60</version>
        </dependency>
      <!--=================mybatis整合spring依赖===============-->
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.2</version>
      </dependency>
      <!--=================mybatis整合spring依赖===============-->
      <!--=================spring依赖===============-->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.8.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>3.2.7.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>3.1.3.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.3.8.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.8.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.8.1</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.0.9.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.0.9.RELEASE</version>
      </dependency>
      <!--=================spring依赖===============-->
    
      <!--=================切面依赖===============-->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.3.8.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.2</version>
      </dependency>
      <!--=================切面依赖===============-->
    </dependencies>
    

    web.xml 配置spring 和springmvc容器

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                          http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
      <servlet>
        <servlet-name>hellomybatis</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>
            WEB-INF/hellomybatis-servlet.xml
          </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>hellomybatis</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applicationContext.xml</param-value>
      </context-param>
    
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    
    </web-app>
    

    hellomybatis-servlet.xml springmvc配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
            http://www.springframework.org/schema/tx
             http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
    
        <!--spring mvc容器扫描配置-->
    <context:component-scan base-package="com.self" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    

    applicationContext.xml spring配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
            http://www.springframework.org/schema/tx
             http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
        <!--spring 容器扫描配置-->
        <context:component-scan base-package="com.self">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/hello_mybatis"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </bean>
    
        <!-- 添加事务支持 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
        <!-- 注册事务管理驱动 表示支持声明式事务 @Transactional 注解标注的会被代理实现事务,但要用在有接口的public方法中-->
        <!--基于注解的方式使用事务配置声明-->
        <tx:annotation-driven transaction-manager="transactionManager" />
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--dataSource连接池-->
            <property name="dataSource" ref="dataSource"/>
            <!--configLocation属性指定mybatis的核心配置文件-->
            <!--如果想把下面整个mybatis-config.xml文件property注释删除了,那么在 UserMapper.xml 这些文件里的type就要配置成全路径的格式如com.self.bean.Side
             否则会找不到bean-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <!-- 所有配置的mapper文件 该配置相当于是mybatis-config.xml里的mappers配置,在这边直接扫描获取了-->
            <property name="mapperLocations" value="classpath*:com/self/dao/*.xml"/>
            <!--typeAliasesPackage:批量别名处理 通过这些property就可以把mybatis-config.xml替代掉了-->
            <property name="typeAliasesPackage" value="com.self.bean"/>
         </bean>
        <!-- Mapper代理开发,使用Spring自动扫描MyBatis的接口并装配 (Spring将指定包中的所有被@Mapper注解标注的接口自动装配为MyBatis的映射接口) -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!-- mybatis-spring组件的扫描器(UserMapper.java),com.dao只需要接口(接口方法与SQL映射文件中的相同) -->
            <property name="basePackage" value="com.self.dao"/>
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        </bean>
    </beans>
    

    mybatis-config.xml mybaits配置文件可以不写了

    <?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>
        <!--mybatis-config.xml可以不用配置,直接通过扫描来配置mapper-->
    <!--   <typeAliases>
            <typeAlias alias="User" type="com.self.bean.User" />
            <typeAlias type="com.self.bean.Side" alias="Side"/>
            <typeAlias type="com.self.bean.UserSide" alias="UserSide"/>
            <typeAlias type="com.self.bean.Weibo" alias="Weibo"/>
        </typeAliases>-->
        <!--
        <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/hello_mybatis" />
                    <property name="username" value="root" />
                    <property name="password" value="123456" />
                </dataSource>
            </environment>
        </environments>
    -->
       <!-- <mappers>
            <mapper resource="com/self/dao/UserMapper.xml" />
            <mapper resource="com/self/dao/SideMapper.xml"/>
            <mapper resource="com/self/dao/UserSideMapper.xml"/>
        </mappers>-->
    </configuration>
    

    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">
      <select id="getUsers" resultType="User">
            select * from `t_user` where 1 = 1
        </select>
    </mapper>
    
    @Repository
    //@Mapper
    public interface UserMapper {
        public List<User> getUsers();
    }
    
    public interface UserService {
        public List<User> getUsers();
    }
    
    @Service("userService")
    public class UserServiceImpl implements UserService {
        @Override
        public List<User> getUsers() {
            return userMapper.getUsers();
        }
    }
    
    @Controller
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping("/user")
        public void getUsers(){
            System.out.println(JSON.toJSONString(userService.getUsers()));
        }
    
    }
    

    输出:

    [{"dept":"amy empire","height":1.75,"id":1,"name":"艾米","phone":"18956563228"},{"dept":"amy empire","height":1.85,"id":2,"name":"大青山","phone":"18956563229"},{"dept":"amy empire","height":1.83,"id":3,"name":"池寒枫","phone":"22056545"},{"dept":"森林矮人王国","height":1.56,"id":4,"name":"霍恩斯","phone":"852-253521"}]
    

    报错:

    1、@RequestMapping("/user") 注解用不了。

    <!--=================需要依赖 spring-web===============-->
       <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>4.0.9.RELEASE</version>
        </dependency>
    

    2、import不了DispatcherServlet

    <!--=================需要依赖 spring-webmvc===============-->
         <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>4.0.9.RELEASE</version>
        </dependency>
    

    3、No bean named 'userController' available,找不到bean。报这个错是因为使用容器扫描配置时注释了过滤的Controller类型,但是没有把use-default-filters="false" 配置删了,倒置没有过滤的Controller配置的话,那么默认是全部过滤,就没有bean实例被扫描进去了。要改成下面这样。

    Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userController' available
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
    
    
    <!--spring 容器扫描配置 错误配置-->
    <context:component-scan base-package="com.self" use-default-filters="false">
        <!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
    </context:component-scan>
    
    <!--spring 容器扫描配置  正确配置-->
        <context:component-scan base-package="com.self" >
        </context:component-scan>
    

    context:component-scan除了具有context:annotation-config的功能之外,context:component-scan还可以在指定的package下扫描以及注册javabean 。还具有自动将带有@component,@service,@Repository等注解的对象注册到spring容器中的功能。

    因此当使用 context:component-scan 后,就可以将 context:annotation-config移除。

    4、Result Maps collection already contains value for com.self.dao.SideMapper.sideMap .集合容器里已经有该类型的值了。这个报错是因为当配置了mybatis-config.xml文件的mappers的同时还注册了MapperScannerConfigurer 的自动扫描MyBatis的接口并装配。注册了两遍。因此只要配置一个就行了,我这边是把mybatis-config.xml文件注释掉了。

    Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'file [F:selfhellomybatis	argetclassescomselfdaoSideMapper.xml]'. Cause: java.lang.IllegalArgumentException: Result Maps collection already contains value for com.self.dao.SideMapper.sideMap
    
    
    <?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>
        <!--mybatis-config.xml可以不用配置,直接通过扫描来配置mapper-->
    <!--   <typeAliases>
            <typeAlias alias="User" type="com.self.bean.User" />
            <typeAlias type="com.self.bean.Side" alias="Side"/>
            <typeAlias type="com.self.bean.UserSide" alias="UserSide"/>
            <typeAlias type="com.self.bean.Weibo" alias="Weibo"/>
        </typeAliases>-->
        <!--
        <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/hello_mybatis" />
                    <property name="username" value="root" />
                    <property name="password" value="123456" />
                </dataSource>
            </environment>
        </environments>
    -->
       <!-- <mappers>
            <mapper resource="com/self/dao/UserMapper.xml" />
            <mapper resource="com/self/dao/SideMapper.xml"/>
            <mapper resource="com/self/dao/UserSideMapper.xml"/>
        </mappers>-->
    </configuration>
    

    5、Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userService'。注册userControllerbean时依赖的userService不能得到的注入。

    这个原因还是出在spring 容器扫描配置配置上,use-default-filters="false" 使用不当。

     org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.self.service.UserService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    	
    
    
        <!--spring 容器扫描配置-->
        <context:component-scan base-package="com.self"  use-default-filters="false">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        
            <!--spring 容器扫描配置-->
        <context:component-scan base-package="com.self">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    

    use-default-filters 属性的默认值为 true,即使用默认的 Filter 进行包扫描,而默认的 Filter 对标有 @Service,@Controller和@Repository 的注解的类进行扫描。设置为 false,即不使用默认的 Filter 进行扫描。也就是不扫描,只扫描下面配置的include-filter,下面配置的扫描注解有几个就只扫几个,有一个就扫一个。

    我们希望 SpringMVC容器 只来控制网站的跳转逻辑,所以我们只希望 SpringMVC 的配置扫描 @Controllerce 注解标注的类,不希望它扫描其余注解标注的类,所以设置了 use-default-filters 为 false,并使用 context:include-filter 子标签设置其只扫描带有 @Controller 注解标注的类。

    Spring 容器就不同了,我们希望 Spring 只不扫描带有 @Controller 注解标注的类,而扫描其他注解标注的类,而这时建立在使用默认的 Filter 进行扫描的基础上,设置了 context:exclude-filter 标签,不扫描 @Controller 注解标注的类,所以不应该设置 use-default-filters 为 false 。

    use-default-filters="false" 需要和 context:include-filter 一起使用,而不能和 context:exclude-filter 属性一起使用。

    参考

    MyBatis分页

    分页可以分为逻辑分页和物理分页。

    逻辑分页是我们的程序在显示每页的数据时,首先查询得到表中的1000条数据,然后根据当前页的“页码”选出其中的100条数据来显示。 物理分页是程序先判断出该选出这1000条的第几条到第几条,然后数据库根据程序给出的信息查询出程序需要的100条返回给我们的程序。

    分页待学习其他的方法,这个不好。

    MyBatis动态SQL语句

    mybatis 的动态sql语句是基于OGNL表达式的。可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:

    1. if 语句 (简单的条件判断)

    2. choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似.

    3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)

    4. where (主要是用来简化sql语句中where条件判断的,能智能的处理 and or ,不必担心多余导致语法错误)

    5. set (主要用于更新时)

    6. foreach (在实现 mybatis in 语句查询时特别有用)

      <select id="getUsersByCond" resultType="User" parameterType="User">
           select * from `t_user` where 1 = 1
           <if test="name != null">
               and name = #{name}
           </if>
           <if test="phone != null">
               and phone = #{phone}
           </if>
           <if test="author != null and author.name != null">
               AND author_name like #{author.name}
           </if>
       </select>
      
       <select id="getUsersByCondition" resultType="User" parameterType="User">
           select * from `t_user`
           <where>
               <if test="name != null">
                   and name = #{name}
               </if>
               <if test="phone != null">
                   and phone = #{phone}
               </if>
               <if test="dept != null">
                   and dept = #{dept}
               </if>
           </where>
       </select>
      

       <select id="getUsersByCondition" resultType="User" parameterType="User">
           select * from `t_user`
           <trim prefix="where" prefixOverrides="and|or">
               <if test="name != null">
                   and name = #{name}
               </if>
               <if test="phone != null">
                   and phone = #{phone}
               </if>
               <if test="dept != null">
                   and dept = #{dept}
               </if>
           </trim>
       </select>
      
      <update id="update" parameterType="User">
           update t_user
           <set>
               <if test="name != null">
                   name = #{name},
               </if>
               <if test="dept != null">
                   dept = #{dept},
               </if>
               <if test="phone != null">
                   phone = #{phone},
               </if>
               <if test="height != null">
                   height = #{height},
               </if>
               <if test="modifyEmp != null">
                   modify_emp = #{modifyEmp},
               </if>
               <if test="modifyTime != null">
                   modify_time = #{modifyTime},
               </if>
           </set>
           where id = #{id}
       </update>
      
      update t_user name = #{name}, dept = #{dept}, phone = #{phone}, height = #{height}, modify_emp = #{modifyEmp}, modify_time = #{modifyTime}, where id = #{id}
       <select id="getUsersByCondition" resultType="User" parameterType="User">
           <bind name="deptBlur" value="'%' + dept + '%'"></bind>
           select * from `t_user`
           <where>
               <if test="name != null">
                   and name = #{name}
               </if>
               <if test="phone != null">
                   and phone = #{phone}
               </if>
               <if test="dept != null">
                   and dept like  #{deptBlur}
               </if>
               <if test="ids != null">
                   and id in
                   <foreach collection="ids" item="id" open="(" close=")" separator=",">
                       #{id}
                   </foreach>
               </if>
           </where>
       </select>
      

      insert id="insert">


      select seq_users.nextval from dual


      select nextval for seq_users from sysibm.sysdummy1"


      insert into users values (#{id}, #{name})

    prefixOverrides使用参考

    foreach查询的写法

    public class User {
    
        /**
         * 成员所属势力群
         */
        private List<Side> sides;
        /**
         * id
         */
        private int id;
    
        private List<Integer> ids;
    
        private Integer[] idsArr;
        /**
         * 名字
         */
        private String name;
        /**
         * 部门,帝国
         */
        private String dept;
        /**
         * 联系号码
         */
        private String phone;
        /**
         * 身高
         */
        private BigDecimal height;
    
        //private List<Weibo> weibos;
        /**
         * 创建人
         */
        private Long createEmp;
        /**
         * 创建时间
         */
        private Date createTime;
        /**
         * 修改人
         */
        private Long modifyEmp;
        /**
         * 修改时间
         */
        private Date modifyTime;
    
        public Integer[] getIdsArr() {
            return idsArr;
        }
    
        public void setIdsArr(Integer[] idsArr) {
            this.idsArr = idsArr;
        }
    
        public List<Integer> getIds() {
            return ids;
        }
    
        public void setIds(List<Integer> ids) {
            this.ids = ids;
        }
        }
    

    测试类:

     User user = new User();
    Integer[] idsArr = {1,2,3,4};
    user.setIdsArr(idsArr);
    user.setDept("amy empire");
    uc.getUserCondition(user);
    //===============================================
     User user = new User();
     List<Integer> ids = new ArrayList<>();
     ids.add(1);
     ids.add(2);
     ids.add(3);
     user.setIds(ids);
     user.setDept("amy empire");
     uc.getUserCondition(user);                    
    

    mybaits if标签语句

    实例:

        <select id="getUsersByCondition" resultType="User" parameterType="User">
            select * from `t_user`
            <where>
                <if test="name != null and name !='' ">
                    and name = #{name,jdbcType=VARCHAR}
                </if>
                <if test="phone != null and phone !='' ">
                    and phone = #{phone,jdbcType=VARCHAR}
                </if>
                <if test="dept != null and dept != '' ">
                    <!-- 另外一种模糊查询%的拼接方法 -->
                    and dept like CONCAT(CONCAT('%', #{dept,jdbcType=VARCHAR}),'%')
                </if>
                <if test="ids != null">
                    and id in
                    <foreach collection="ids" item="id" open="(" close=")" separator=",">
                        #{id}
                    </foreach>
                </if>
            </where>
        </select>
    

    错误:

    里的连接词 and 不能大写,否则会识别不了,要用小写的and。因为mybatis区分大小写,and是约定的关键字,应该用小写的and。

    Exception in thread "main" org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'name != null AND name !='' '. Cause: org.apache.ibatis.ognl.ExpressionSyntaxException: Malformed OGNL expression: name != null AND name !=''  [org.apache.ibatis.ognl.ParseException: Encountered " <IDENT> "AND "" at line 1, column 14.
    Was expecting one of:
    
     <if test="phone != null and phone !='' ">
                    AND phone = #{phone,jdbcType=VARCHAR}
    </if>
    <!-- 下面才是正确写法 -->
     <if test="phone != null and phone !='' ">
                    and phone = #{phone,jdbcType=VARCHAR}
    </if>
    

    !和= 之间多了一个空格也会报错,if test="phone ! = null and phone ! ='' 。应该去掉空格

    <!-- 下面才是正确写法 -->
     <if test="phone != null and phone !='' ">
                    and phone = #{phone}
    </if>
    

    MyBatis where标签语句

    “where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以 AND 或OR 开头的,则它会剔除掉。

    Mybatis set标签

    当 update 语句中没有使用 if 标签时,如果有一个参数为 null,都会导致错误。

    当在 update 语句中使用if标签时,如果前面的if没有执行,则或导致逗号多余错误。使用set标签可以将动态的配置 SET 关键字,并剔除追加到条件末尾的任何不相关的逗号。使用 if+set 标签修改后,如果某项为 null 则不进行更新,而是保持数据库原值。
    

    报错:如果 set 包含的内容为空的话则会出错 ,如下。

    update t_user                    where id = ?
    ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where id = 2' at line 3
    ;
    

    Mybatis trim标签

    trim 是更灵活用来去处多余关键字的标签,它可以用来实现 where 和 set 的效果。trim 元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是 prefix 和 suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是 prefixOverrides 和 suffixOverrides;正因为 trim 有这样的功能,所以我们也可以非常简单的利用 trim 来代替 where 元素的功能。

    choose (when, otherwise)标签

    有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。而使用if标签时,只要test中的表达式为 true,就会执行 if 标签中的条件。MyBatis 提供了 choose 元素。if标签是与(and)的关系,而 choose 是或(or)的关系。

    choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。 
    

    MyBatis SqlSessionDaoSupport实例

    待验证。没用

    MyBatis打印输出SQL语句

    实例:

    log4j.properties

    log4j.rootLogger=debug,stdout,logfile
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    #log4j.appender.stdout.Target=System.err
    log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
    log4j.appender.logfile=org.apache.log4j.FileAppender
    log4j.appender.logfile.File=C:/mybatis_show_sql.log
    log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
    log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n
    
    log4j.logger.com.ibatis=DEBUG
    log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
    log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
    log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
    log4j.logger.java.sql.Connection=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    

    pom.xml依赖

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.2</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.21</version>
    </dependency>
    

    输出:

    DEBUG - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@647f63b4] was not registered for synchronization because synchronization is not active
    DEBUG - Fetching JDBC Connection from DataSource
    DEBUG - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/hello_mybatis]
    DEBUG - JDBC Connection [com.mysql.jdbc.JDBC4Connection@481b3df0] will not be managed by Spring
    DEBUG - ==>  Preparing: select * from `t_user` WHERE id in ( ? , ? , ? ) 
    DEBUG - ==> Parameters: 1(Integer), 2(Integer), 3(Integer)
    DEBUG - <==      Total: 3
    DEBUG - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@647f63b4]
    DEBUG - Returning JDBC Connection to DataSource
    ERROR - [{"dept":"amy empire","height":1.75,"id":1,"name":"大青山","phone":"18956563228"},{"dept":"amy empire","height":1.85,"id":2,"name":"艾米哈珀","phone":"18956563228"},{"dept":"amy empire","height":1.83,"id":3,"name":"池寒枫","phone":"22056545"}]
    

    疑问:

    Q:什么是OGNL表达式?

    A:对象导航图语言(Object Graph Navigation Language),简称OGNL,是应用于Java中的一个开源的表达式语言(Expression Language),它被集成在mybatis等框架中,作用是对数据进行访问,它拥有类型转换、访问对象方法、操作集合对象等功能。

    Q:像下面这种变量要怎么配置各个环境的变量,方便替换,怎么读取到相应的properties文件?value="${driver}"

    <?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="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
      <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      </mappers>
    </configuration>
    

    Q:MyBatis ofType和javaType区别?

    A:JavaType和ofType都是用来指定对象类型的,但是JavaType是用来指定pojo中属性的类型,而ofType指定的是映射到list集合属性中pojo的类型。

    Q:下面两个resultMap有什么区别么?为什么要多指导jdbcType 和javaType,去掉这两个后运行程序还是正常,那这两个有什么作用?

        <resultMap id="userMap" type="User">
            <result property="id" column="user_id"/>
            <result property="name" column="name"/>
            <result property="dept" column="dept"/>
            <result property="phone" column="phone"/>
            <collection property="weibos" ofType="com.self.bean.Weibo" column="user_id">
                <!--<id property="id" column="t_weibo.id" javaType="int" jdbcType="INTEGER"  />-->
                <!--不加表别名或者表名来区分id的话会导致查询不出多条数据-->
                <id property="id" column="p.id" />
                <result property="title" column="title" />
                <result property="content" column="content" />
            </collection>
        </resultMap>
        <!--===========================分割===========================-->
    	<resultMap id="userMap" type="User">
            <result property="id" column="user_id"/>
            <result property="name" column="name"/>
            <result property="dept" column="dept"/>
            <result property="phone" column="phone"/>
            <collection property="weibos" ofType="com.self.bean.Weibo" column="user_id">
                <!--<id property="id" column="t_weibo.id" javaType="int" jdbcType="INTEGER"  />-->
                <!--不加表别名或者表名来区分id的话会导致查询不出多条数据-->
                <id property="id" column="p.id" javaType="int" jdbcType="INTEGER"  />
                <result property="title" column="title" javaType="string" jdbcType="VARCHAR"/>
                <result property="content" column="content" javaType="string" jdbcType="VARCHAR"/>
            </collection>
        </resultMap>
    

    Q:@Mapper注解的作用是什么?

    @Mapper
    public interface UserMapper {}
    

    Q:在写mybatissql时为什么查询绑定的值还要指定上jdbcType类型呢?不写也是可以的,写和不写的区别?如下

    and phone = #{phone,jdbcType=VARCHAR}
    

    Q:有空研究下log4j.properties上的具体配置如何操作,自定义,形成文档。

  • 相关阅读:
    面向对象思想
    jQuery随笔
    总结关于linux操作
    转.linux上安装python
    sql server 基本语句
    linux 常见指令
    loadrunner 录制时不自动弹出网页
    Linux 安装MySQL
    linux关于安装
    loadrunner 性能测试
  • 原文地址:https://www.cnblogs.com/castamere/p/12654606.html
Copyright © 2011-2022 走看看