• mybatis笔记(一)入门程序、dao开发方式、mapper开发方式、全局配置文件、映射文件、动态sql


    录:

    1、mybatis的介绍
    2、分析jdbc的问题
    3、mybatis框架原理
    4、mybatis入门程序
    5、主键策略
    6、小结
    7、mybatis开发dao的方式--原始dao开发方式
    8、mybatis开发dao的方式--Mapper代理的开发方式
    9、全局配置文件
    10、映射文件--输入参数
    11、映射文件--输出结果
    12、动态sql
    13、mybatis与hibernate的区别及各自应用场景

    1、mybatis的介绍    <--返回目录

        * mybatis就是一个封装了jdbc的【持久层框架】,它和hibernate都属于ORM(Object Relational Mapping对象关系映射)框架,
          但是具体来说,hibernate是一个完全的orm框架,而mybatis是一个不完全的orm框架
        * Mybatis让程序员只关注sql本身,而不需要去关注连接的创建、statement的创建等操作。
        * Mybatis会将输入参数、输出结果进行映射。

    2、分析jdbc的问题    <--返回目录

      原生态的jdbc代码

    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        
        try {
            //1、加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2、通过驱动管理类获取数据库连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
            //3、定义sql语句 ?表示占位符
            String sql = "select * from user where username = ?";
            //4、获取预处理statement
            preparedStatement = connection.prepareStatement(sql);
            //5、给sql语句中的?赋值;设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
            preparedStatement.setString(1, "王五");
            //6、向数据库发出sql执行查询,查询出结果集
            resultSet = preparedStatement.executeQuery();
            //7、遍历结果集
            while(resultSet.next()){
                System.out.println(resultSet.getString("id")+"  "+resultSet.getString("username"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //8、释放资源
            if(resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    View Code

      问题总结
        1)在创建连接时,存在硬编码
              配置文件(全局配置文件)
              2)在执行statement时存在硬编码
              配置文件(映射文件)
              3)频繁的开启和关闭数据库连接,会造成数据库性能下降。
              数据库连接池(全局配置文件)

    3、mybatis框架原理    <--返回目录

    4、mybatis入门程序    <--返回目录

      选中 config文件夹, 右键-> Build Path -> Use as Source Folder

      

       需求:对订单商品案例中的用户表进行增删改查操作
        1) 根据用户ID查询用户信息--加载load
        2) 根据用户名称模糊查询用户列表--列表展示list,带条件的分页查询
        3) 添加用户
        4) 删除用户
        5) 修改用户

      环境准备
        - Jdk:1.8
        - IDE:eclipse
        - Mybatis:3.2.7
        - 数据库:MySQL 5.X

      下载mybatis: mybaits的代码由github.com管理,下载地址:https://github.com/mybatis/mybatis-3/releases


      sql 脚本

    create database db_mybatis_01 default character set utf8;
    use db_mybatis_01;
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) NOT NULL COMMENT '用户名称',
      `birthday` date DEFAULT NULL COMMENT '生日',
      `sex` char(1) DEFAULT NULL COMMENT '性别',
      `address` varchar(256) DEFAULT NULL COMMENT '地址',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
    
    insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) 
    values (1,'王五',NULL,'2',NULL),
    (2,'张三','2014-07-10','1','北京市'),
    (3,'张小明',NULL,'1','河南郑州'),
    (4,'陈小明',NULL,'1','河南郑州'),
    (5,'张三丰',NULL,'1','河南郑州'),
    (6,'陈小明',NULL,'1','河南郑州'),
    (7,'王五',NULL,NULL,NULL);

      导入jar包
        - 核心jar:mybatis-3.2.7.jar
        - 依赖jar:lib目录下,9个
        - mysql 驱动:mysql-connector-java-5.1.40-bin.jar

     

       创建全局配置文件

    <?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>
    
        <!-- 加载properties文件或者声明属性信息 <property name="db.username" value="123" /> -->
        <properties resource="db.properties">
        </properties>
    
        <!-- <settings></settings> -->
    
        <!-- 自定义别名 -->
        <typeAliases>
            <!-- 单个别名定义 -->
            <!-- <typeAlias type="com.oy.mybatis.po.User" alias="user"/> -->
    
            <!-- 批量别名定义(推荐) -->
            <!-- package:指定包名称来为该包下的po类声明别名,默认的别名就是类名(首字母大小写都可) -->
            <!-- <package name="com.oy.mybatis.po" /> -->
        </typeAliases>
    
        <!-- 配置mybatis的环境信息,与spring整合后,该信息由spring来管理 -->
        <environments default="development">
            <environment id="development">
                <!-- 配置JDBC事务控制,由mybatis进行管理 -->
                <transactionManager type="JDBC"></transactionManager>
                <!-- 配置数据源,采用mybatis连接池 -->
                <dataSource type="POOLED">
                    <property name="driver" value="${db.driver}" />
                    <property name="url" value="${db.url}" />
                    <property name="username" value="${db.username}" />
                    <property name="password" value="${db.password}" />
                </dataSource>
            </environment>
        </environments>
    
        <!-- 加载映射文件 -->
        <mappers>
            <mapper resource="User.xml" />
            <!-- <mapper resource="mapper/UserMapper.xml" /> -->
    
            <!-- 批量加载映射文件 -->
            <!-- <package name="com.oy.mybatis.mapper" /> -->
        </mappers>
    </configuration>

      数据库的配置文件    db.properties

    db.driver=com.mysql.jdbc.Driver
    db.url=jdbc:mysql://localhost:3306/db_mybatis_01?useUnicode=true&characterEncoding=utf8
    db.username=root
    db.password=

      log4j.properties

    # Global logging configuration
    log4j.rootLogger=DEBUG, stdout
    # Console output...
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

      或

    log4j.rootLogger=info,appender1,appender2
    
    log4j.appender.appender1=org.apache.log4j.ConsoleAppender 
    
    log4j.appender.appender2=org.apache.log4j.FileAppender 
    log4j.appender.appender2.File=d:/logFile.txt
     
    log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout
    log4j.appender.appender2.layout=org.apache.log4j.TTCCLayout  

      User 实体类

    package com.oy.domain;
    
    import java.sql.Date;
    
    public class User {
        private int id;
        private String username; // 用户名
        private Date birthday; // 生日
        private String sex; // 性别
        private String address; // 地址
    
        // getXxx和setXxx
    
        @Override
        public String toString() {
            return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address="
                    + address + "]";
        }
    }

      映射文件 User.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:命名空间,对statement的信息进行分类管理 -->
    <!-- 注意:在mapper代理时,它具有特殊及重要的作用 -->
    <mapper namespace="test">
        <!-- 根据用户ID查询用户信息 -->
        <!-- select:表示一个MappedStatement对象 -->
        <!-- id:statement的唯一标示 -->
        <!-- #{}:表示一个占位符? -->
        <!-- #{id}:里面的id表示输入参数的参数名称,如果该参数是简单类型,那么#{}里面的参数名称可以任意 -->
        <!-- parameterType:输入参数的java类型 -->
        <!-- resultType:输出结果的所映射的java类型(单条结果所对应的java类型) -->
        <select id="findUserById" parameterType="int" resultType="com.oy.domain.User">
            SELECT * FROM USER WHERE id =#{id}
        </select>
    
        <select id="findUsersByName" parameterType="java.lang.String" resultType="com.oy.domain.User">
            SELECT * FROM USER WHERE username LIKE '%${value}%'
        </select>
        
        <!-- 添加用户 -->
        <!-- selectKey:查询主键,在标签内需要输入查询主键的sql -->
        <!-- order:指定查询主键的sql和insert语句的执行顺序,相当于insert语句来说(表示:什么时候获取主键id,是在insert语句之前,还是之后) -->
        <!-- LAST_INSERT_ID:该函数是mysql的函数,获取自增主键的ID,它必须配合insert语句一起使用 -->
        <insert id="insertUser" parameterType="com.oy.domain.User">
            <selectKey keyProperty="id" resultType="int" order="AFTER">    
                SELECT LAST_INSERT_ID()         
            </selectKey>
        
            INSERT INTO USER(username,birthday,sex,address)
            VALUES(#{username},#{birthday},#{sex},#{address})
        </insert>
        
        <!-- 删除用户 -->
        <delete id="deleteUserById" parameterType="int">
            delete from user where id = #{id}
        </delete>
        
        <!-- 修改用户 -->
        <update id="updateUserById" parameterType="int">
            update user set username = '张小三' where id = #{id}
        </update>
        
        
    </mapper>

      测试类

    package com.oy.test;
    
    import java.io.InputStream;
    import java.util.List;
    
    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 org.junit.jupiter.api.Test;
    
    import com.oy.domain.User;
    
    public class Test1 {
        /**
         * 按id查询用户
         * @throws Exception
         */
        @Test
        public void findUserByIdTest() throws Exception {
            //读取配置文件
            //全局配置文件的路径
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            
            //创建SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            
            //创建SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
            
            //调用SqlSession的增删改查方法
            //第一个参数:表示statement的唯一标示
            User user = sqlSession.selectOne("test.findUserById", 1);
            System.out.println(user);
            
            //关闭资源
            sqlSession.close();
        }
        
        /**
         * 按username查询用户
         * @throws Exception
         */
        @Test
        public void findUsersByNameTest() throws Exception{
            //读取配置文件
            //全局配置文件的路径
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            
            //创建SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            
            //创建SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
            
            //调用SqlSession的增删改查方法
            //第一个参数:表示statement的唯一标示
            List<User> list = sqlSession.selectList("test.findUsersByName", "小明");
            for(User user:list){
                System.out.println(user);
            }
            //关闭资源
            sqlSession.close();
        }
        
        /**
         * 添加用户
         * @throws Exception
         */
        @Test
        public void insertUserTest() throws Exception{
            //读取配置文件
            //全局配置文件的路径
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            
            //创建SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            
            //创建SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
            
            User user = new User();
            user.setUsername("东哥hm19");
            user.setAddress("宝盛西里24号楼");
            
            //调用SqlSession的增删改查方法
            //第一个参数:表示statement的唯一标示
            sqlSession.insert("test.insertUser", user);
            
            int id = user.getId();
            //System.out.println(user.getId());
            User user2 = sqlSession.selectOne("test.findUserById", id);
            System.out.println(user2);
            
            //提交事务
            sqlSession.commit();
            //关闭资源
            sqlSession.close();
        }
        
        /**
         * 删除用户
         * @throws Exception
         */
        @Test
        public void deleteUserByIdTest() throws Exception{
            //读取配置文件
            //全局配置文件的路径
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            
            //创建SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            
            //创建SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
            
            //调用SqlSession的增删改查方法
            //第一个参数:表示statement的唯一标示
            //先查询要删除的user,然后删除
            User user = sqlSession.selectOne("test.findUserById", 28);
            System.out.println(user);
            sqlSession.delete("test.deleteUserById", 28);
            
            //提交事务
            sqlSession.commit();
            //关闭资源
            sqlSession.close();
        }
        
        /**
         * 按id修改用户
         * @throws Exception
         */
        @Test
        public void updateUserByIdTest() throws Exception{
            //读取配置文件
            //全局配置文件的路径
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            
            //创建SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            
            //创建SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
            
            //调用SqlSession的增删改查方法
            //第一个参数:表示statement的唯一标示
            User user = sqlSession.selectOne("test.findUserById", 10);
            System.out.println(user);
            sqlSession.update("test.updateUserById", 10);
            User user2 = sqlSession.selectOne("test.findUserById", 10);
            System.out.println(user2);
            
            //提交事务
            sqlSession.commit();
            //关闭资源
            sqlSession.close();
        }
    }

    5、主键策略    <--返回目录

      主键策略为自增时的执行顺序为:order="AFTER"   

    INSERT  INTO `user`(`username`,`birthday`,`sex`,`address`) VALUES ('王五',NULL,'2',NULL);
    SELECT LAST_INSERT_ID();       //在insert语句执行完后,获取id。即获取上面记录的id

      主键策略为:uuid

    <!-- 主键策略为:UUID -->
    <insert id="insertUser2" parameterType="com.oy.domain.User">
        <selectKey keyProperty="id" resultType="string" order="BEFORE">
            SELECT UUID() 
        </selectKey>
    
        INSERT INTO USER
        (id,username,birthday,sex,address)
        VALUES(#{id},#{username},#{birthday},#{sex},#{address})
    </insert>

      主键策略为uuid时的执行顺序为:order="BEFORE"   

    SELECT UUID();
    INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address});

      主键返回值序列:序列也就是sequence,它是Oracle的主键生成策略

    <!-- 主键之sequence -->
    <insert id="insertUser3" parameterType="com.oy.domain.User">
        <selectKey keyProperty="id" resultType="int" order="BEFORE">
            SELECT seq.nextval FROM dual
        </selectKey>
    
        INSERT INTO USER
        (id,username,birthday,sex,address)
        VALUES(#{id},#{username},#{birthday},#{sex},#{address})
    </insert>        

     

    6、小结     <--返回目录

        * #{}和${}
            #{}表示占位符?,#{}接收简单类型的参数时,里面的名称可以任意
            ${}表示拼接符,${}接收简单类型的参数时,里面的名称必须是value
            ${}里面的值会原样输出,不加解析(如果该参数值是字符串,也不会添加引号)
            ${}存在sql注入的风险,但是有些场景下必须使用,比如排序后面会动态传入排序的列名
                    
        * parameterType和resultType
            parameterType指定输入参数的java类型,parameterType只有一个,也就是说入参只有一个。
            resultType指定输出结果的java类型(是单条记录的java类型)
            
        * selectOne和selectList
            selectOne查询单个对象
            selectList查询集合对象

    7、mybatis开发dao的方式--原始dao开发方式    <--返回目录

      原始dao开发方式:开发dao接口和dao实现类,由ibatis遗留下来的风格

       dao接口和实现类

    public interface UserDao {
        public User findUserById(int id);
        public List<User> findUsersByName(String name);
        public void insertUser(User user);
        public void deleteUserById(int id);
        public void updateUserById(int id);
    }
    
    public class UserDaoImpl implements UserDao {
        
        private SqlSessionFactory sqlSessionFactory;
        public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
            this.sqlSessionFactory = sqlSessionFactory;
        }
    
        /**
         * 按id查询用户
         */
        @Override
        public User findUserById(int id) {
            // 创建SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            User user = sqlSession.selectOne("test.findUserById", id);
            // 关闭资源
            sqlSession.close();
            return user;
        }
    
        /**
         * 按username查询用户
         */
        @Override
        public List<User> findUsersByName(String name) {
            // 创建SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            List<User> userList = sqlSession.selectList("test.findUserByName", name);
            return userList;
        }
    
        /**
         * 添加用户
         */
        @Override
        public void insertUser(User user) {
            // 创建SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            sqlSession.insert("test.insertUser", user);
        }
    
        /**
         * 按id删除用户
         */
        @Override
        public void deleteUserById(int id) {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            sqlSession.update("test.deleteUserById", id);
        }
    
        /**
         * 按id修改用户
         */
        @Override
        public void updateUserById(int id) {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            sqlSession.update("test.updateUserById", id);
        }
    
    }

      其他与上一项目一致。

      测试类

    package com.oy.test;
    
    import java.io.InputStream;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.oy.dao.UserDao;
    import com.oy.dao.UserDaoImpl;
    import com.oy.domain.User;
    
    public class Test1 {
        private SqlSessionFactory sqlSessionFactory;
    
        @Before
        public void setUp() throws Exception {
            // 读取配置文件
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
    
            // 创建SqlSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }
    
        @Test
        public void testFindUserById() throws Exception {
            // 创建UserDao
            UserDao dao = new UserDaoImpl(sqlSessionFactory);//注入sqlSessionFactory
            
            User user = dao.findUserById(1);
            System.out.println(user);
        }
    
    }

    8、mybatis开发dao的方式--Mapper代理的开发方式    <--返回目录

      Mapper代理使用的是jdk的代理策略。
      Mapper代理的开发规范
        1)mapper接口的全限定名要和mapper映射文件的namespace值一致。
        2)mapper接口的方法名称要和mapper映射文件的statement的id一致。
        3)mapper接口的方法参数类型要和mapper映射文件的statement的parameterType(输入参数类型)的值一致,
         而且它的参数是一个。
        4)mapper接口的方法返回值类型要和mapper映射文件的statement的resultType(返回结果类型)的值一致。

      创建接口 com.oy.mapper.UserMapper   

    public interface UserMapper{
        public User findUserById(int id) throws Exception;   //int id为输入参数   User为输出结果
    }    

      mapper映射文件:在config(源目录,也就是src)下创建mapper目录然后创建UserMapper.xml(这是mybatis的命名规范,当然,也不是必须是这个名称)

    <mapper namespace="com.oy.mapper.UserMapper">  // namespace="com.oy.mapper.UserMapper"与接口全限定名称相同
        <select id="findUserById" parameterType="int" resultType="com.oy.domain.User">   //id="findUserById"与接口方法名称相同
            SELECT * FROM USER WHERE id = #{id}
        </select>
    </mapper>

      SqlMapConfig.xml加载映射文件

    <mappers>    
        <mapper resource="mapper/UserMapper.xml" />
    </mappers>    

      测试代码‘

    private SqlSessionFactory sqlSessionFactory;
    @Before
    public void setUp() throws Exception {        
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);    
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void testFindUserById() throws Exception {
        // 创建UserMapper对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.findUserById(1);
        System.out.println(user);
        sqlSession.close();
    }

    9、全局配置文件    <--返回目录

      SqlMapConfig.xml的配置内容和顺序如下(顺序不能乱):

    Properties(属性)
    Settings(全局参数设置)
    【typeAliases】(类型别名)SSM整合后依然会用到
    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)
    environments(环境信息集合)
        environment(单个环境信息)
            transactionManager(事物)
            dataSource(数据源)
    mappers(映射器)

      property加载的顺序

    1)先加载properties中property标签声明的属性
    2)再加载properties标签引入的properties配置文件中的属性,如果同名,后面会覆盖前面的值
    3)parameterType的值会和properties的属性值发生冲突,如果发现上面已经有同名的属性了,那后面会覆盖前面的值

      mybatis支持的别名

    别名    映射的类型
    _byte     byte 
    _long     long 
    _short     short 
    _int     int 
    _integer     int 
    _double     double 
    _float     float 
    _boolean     boolean 
    string     String    java.lang.String
    byte     Byte 
    long     Long 
    short     Short 
    【int     Integer】 
    integer     Integer 
    double     Double 
    float     Float 
    boolean     Boolean 
    date     Date 
    decimal     BigDecimal 
    bigdecimal     BigDecimal 

      自定义别名   

    <typeAliases>
        <typeAlias type="com.oy.domain.User" alias="user"/>
        <package:指定包名称来为该包下的po类声明别名,默认的别名就是类名(首字母大小写都可)
        <package name="com.oy.domain"/>
    </typeAliases>        

      在SqlMapConfig.xml文件中加载映射文件

    <mapper resource="sqlmap/User.xml" />   相对于类路径src
    <mapper url="file:///D:workspace_spingmvcmybatis_01configsqlmapUser.xml" />    使用完全限定路径
    <mapper class="cn.itcast.mapper.UserMapper"/>注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
    【<package name="cn.itcast.mapper"/>注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;】
    <!-- 加载映射文件 -->
    <mappers>
        <mapper resource="User.xml" />  相对类路径src
        <!-- <mapper resource="mapper/UserMapper.xml" /> -->
    
        <!-- 批量加载映射文件,推荐使用该种方式 -->
        <package name="com.oy.mapper" />
    </mappers>    

    10、映射文件--输入参数    <--返回目录

      parameterType="int等简单类型|pojo类型|包装pojo类型|Map类型"   

      parameterType="Map类型"

    <!-- 传递hashmap综合查询用户信息 -->
    <select id="findUserByHashmap" parameterType="hashmap" resultType="user">
       select * from user where id=#{id} or username like '%${username}%'   //id和username是hashmap的key。
    </select>

      测试

    Public void testFindUserByHashmap()throws Exception{
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //构造查询条件Hashmap对象
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("id", 1);
        map.put("username", "小明");
        
        //传递Hashmap对象查询用户列表
        List<User>list = userMapper.findUserByHashmap(map);
        //关闭session
        session.close();
    }

      异常测试:传递的map中的key和sql中解析的key不一致。测试结果没有报错,只是通过key获取值为空。

    11、映射文件--输出结果    <--返回目录

      resultType="int等简单类型|pojo类型"

      resultType的使用要求:

      - 使用resultType进行结果映射时,需要查询出的列名和映射的对象的属性名一致,才能映射成功。
      - 如果查询的列名和对象的属性名全部不一致,那么映射的对象为空。
      - 如果查询的列名和对象的属性名有一个一致,那么映射的对象不为空,但是只有映射正确那一个属性才有值。
      - 如果查询的sql语句中的列名有别名,那么这个别名就代表列名,别名需要与映射的对象的属性名一致。所以,假如数据库中user表的列名为uid,但是领域对象User的属性为id,在查询时可以指定uid的别名为id

      resultMap的使用要求:使用resultMap进行结果映射时,不需要查询的列名和映射的属性名必须一致。

      但是需要声明一个resultMap,来对列名和属性名进行映射。            
            - 需求:对以下sql查询的结果集进行对象映射 Select id id_,username username_,sex sex_ from user where id = 1;
            - 映射文件

    <resultMap type="user" id="UserRstMap">    //注意type="user",mapper接口中findUserRstMap()方法返回值为User对象
        <id column="id_" property="id"/>   
        <result column="username_" property="username"/>
        <result column="sex_" property="sex"/>
    </resultMap>
    <select id="findUserRstMap" parameterType="int" resultMap="UserRstMap">
        Select id id_,username username_,sex sex_ from user where id = #{id};
    </select>

    12、动态sql    <--返回目录

      在mybatis中,它提供了一些动态sql标签,可以让程序员更快得进行mybatis开发,这些动态sql可以提高sql的可重用性。
      常用的动态sql标签:if标签、where标签、sql片段、foreach标签。

      if标签/where标签

        - 需求:综合查询时,查询条件由用户来输入,用户名称可以为空,需要满足这种情况下的sql编写。
        - 映射文件

    <select id="findUserList" parameterType="com.oy.po.UserQueryVO" resultType="user">  //注明:UserQueryVO是个包装pojo类,
        SELECT * FORM user                                                                //封装了private User user;
        <where>   //<where>的作用:拼接条件,并去除多余的的AND
            <if test="user != null">   //判断当输入参数为空时,做不同处理
                <if test="user.username != null and user.username != ''">
                    AND username LIKE '%${user.username}%'
                </if>
                <if test="user.sex != null and user.sex != ''">
                    AND sex=#{user.sex}
                </if>
            </if>
        </where>
    </select>

      sql片段

      - sql片段可以让代码有更高的可重用性
            - sql片段需要先定义后使用
            - 定义sql片段:

    <!--定义sql片段
        sql片段内,可以定义sql语句的任何部分
        sql片段内,最好不要将where和select关键字声明在内
    -->
    <sql id="whereClause">
        <if test="user != null">
            <if test="user.username != null and user.username != ''">
                AND username LIKE '%${user.username}%'
            </if>
            <if test="user.sex != null and user.sex != ''">
                AND sex=#{user.sex}
            </if>
        </if>
    </sql>

      - 使用sql片段:

    <select id="findUserList" parameterType="com.oy.po.UserQueryVO" resultType="user">  
        SELECT * FORM user                                                                    
        <where>   
            <!--引入sql片段-->    
            <include refid="whereClause"/>    
        </where>
    </select>

      

      foreach标签

      - 可以循环传入参数
            - 需求:综合查询时,会根据用户ID集合进行查询 SELECT * FROM USER WHERE id IN (1,2,10)
            - 修改包装pojo类
              public class UserQueryVO{
                private User user;
                private List<Integer> idList;//商品id集合
              }
            - 映射文件

    <select id="findUserList" parameterType="com.oy.po.UserQueryVO" resultType="user">
        SELECT * FROM USER 
        <where>
            <if test="idLIst != null">
                AND id IN
                <foreach collection="idList" item="id" open="(" close=")" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>                
    </select>        

      - 测试代码

    List<Integet> idList = new ArrayList<Integer>();
    idList.add(1);
    idList.add(2);
    idList.add(10);
    VO.setIdList(idList);
    List<User> list = mapper.findUsreList(VO);

      - 最后发送的sql语句为:SELECT * FROM USER WHERE id IN (?,?,?)

    13、mybatis与hibernate的区别及各自应用场景    <--返回目录

        * Mybatis技术特点:
            1)通过直接编写SQL语句,可以直接对SQL进行性能的优化;
            2)学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
            3)由于直接编写SQL语句,所以灵活多变,代码维护性更好。
            4)不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
            
        * Hibernate技术特点:
            1)标准的orm框架,程序员不需要编写SQL语句。
            2)具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
            3)学习门槛高,需要对数据关系模型有良好的基础,而且在设置ORM映射的时候,需要考虑好性能和对象模型的权衡。
            4)程序员不能自主的去进行SQL性能优化。
            
        * Mybatis应用场景:
            需求多变的互联网项目,例如电商项目。
        * Hibernate应用场景:
            需求明确、业务固定的项目,例如OA项目、ERP项目等。

    ---

  • 相关阅读:
    python字符编码与转码
    python字符编码与转码
    BlackNurse攻击:4Mbps搞瘫路由器和防火墙
    BlackNurse攻击:4Mbps搞瘫路由器和防火墙
    BlackNurse攻击:4Mbps搞瘫路由器和防火墙
    BlackNurse攻击:4Mbps搞瘫路由器和防火墙
    HTML基础
    HTML基础
    小伙做起石化贸易生意,他的创业之路不平坦
    种植苗木基地,村官靠这个成为致富好能手
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/13762548.html
Copyright © 2020-2023  润新知