Mybatis--day01

作者: 键盘瞎 | 来源:发表于2017-03-10 23:29 被阅读244次
    非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿 成长

    什么是Mybatis

    ​ MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
    ​ Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

    单独使用jdbc开发存在的问题

    实现步骤

    1. 加载数据库驱动。根据不同的数据库选择不同的驱动。
    2. 创建一个连接。获得一个Connection对象。
    3. 创建一个prepareStatement对象,封装了sql语句。
    4. 设置参数。
    5. 执行查询获得一个ResultSet对象。
    6. 遍历resultSet对象。

    数据库

    数据库

    代码实现

    存在的问题

    1. 数据库驱动存在硬编码的问题。写到配置文件中来解决。
    2. 数据库连接串、用户名、密码存在硬编码的问题。
    3. Sql语句硬编码
    4. 参数设置不灵活
    5. 查询结果最好是返回一个pojo对象或者是pojo列表。
    6. 每次查询都需要开启连接关闭连接。浪费性能。需要使用数据库连接池。

    Mybatis框架架构

    Mybatis框架架构

    Mybatis的入门程序

    Mybatis的下载

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

    目录结构

    需求

    实现以下功能:
    根据用户id查询一个用户信息
    根据用户名称模糊查询用户信息列表
    添加用户
    更新用户
    删除用户

    入门程序实现

    工程搭建

    第一步:创建一个java工程。
    第二步:导入jar包。包括mybatis的jar包、mybatis依赖的jar包、mysql的数据库驱动。
    第三步:创建一个log4j.properties。方便查看sql语句用的。
    第四步:创建一个SqlMapConfig.xml。配置数据库连接池。
    第五步:创建Mapper映射文件。
    第六步:编码。

    项目

    SqlMapConfig.xml

    在classpath下创建SqlMapConfig.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>
        <!-- 和spring整合后 environments配置将废除 -->
        <environments default="development">
            <environment id="development">
                <!-- 使用jdbc事务管理 -->
                <transactionManager type="JDBC" />
                <!-- 数据库连接池 -->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver" />
                    <property name="url"
                        value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                    <property name="username" value="root" />
                    <property name="password" value="root" />
                </dataSource>
            </environment>
        </environments>
        
        <mappers>
        
        </mappers>
    </configuration>
    

    Mapper映射文件

    习惯上mapper映射文件的名称和数据库的表名一致。Ibatis时代的习惯。

    <?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的作用就是sql语句隔离,后面还有其他用途。 -->
    <mapper namespace="test">
    </mapper>
    

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

    <!-- 加载Mapper映射文件 -->
    <mappers>
        <!-- resource从classpath下开始查找 -->
        <mapper resource="sqlmap/user.xml"/>
    </mappers>
    

    根据用户id查询一个用户信息

    创建一个POJO保存返回结果

    POJO的属性要求和数据库中的字段相对应

    public class User {
    
        private int id;
        private String username;// 用户姓名
        private String sex;// 性别
        private Date birthday;// 生日
        private String address;// 地址
        
        //set和get方法
    }
    

    Sql语句

    select * from user where id = 10

    Mapper文件

    需要把sql语句写到user.xml这个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">
    <!-- namespace的作用就是sql语句隔离,后面还有其他用途。 -->
    <mapper namespace="test">
        <!-- 
            select:如果是一个select语句就需要使用select节点。
            id就是一个sql语句的id,代表一个sql语句。起个名字叫做StatementId。
            parameterType:参数的类型
            resultType:返回结果的类型,可以是pojo类型,需要pojo的全限定名。
            #{}:是一个占位符。相当于jdbc中的“?”,括号内容的名称,如果是简单数据类型可以随便起。
         -->
        <select id="getUserById" parameterType="int" resultType="cn.itcast.pojo.User">
            SELECT * from user where id = #{id}
        </select>
    </mapper>
    

    查询方法

    /**
    * 根据id查询用户信息
    */
    @Test
    public void getUserById() throws Exception {
        //创建一SqlSessionFactory
        //把配置文件读取到流中
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //创建SqlSessionFactory对象
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //创建sqlsession对象
        SqlSession sqlSession = sessionFactory.openSession();
        //查询一条记录使用selectOne方法
        //第一个参数:statementID
        //第二个参数:sql语句用到的参数
        User user = sqlSession.selectOne("test.getUserById", 10);
        System.out.println(user);
        //关闭sqlsession
        sqlSession.close();
    }
    

    根据用户名查询用户

    Sql语句

    SELECT * from user where username LIKE '%张三%'

    第一种方法

    Mapper文件

    <!-- 根据用户名查询用户 -->
    <!-- resultType是返回结果中一条记录的类型 -->
    <select id="getUserByName" parameterType="string" resultType="cn.itcast.pojo.User">
        SELECT * from user where username LIKE #{name}
    </select>
    

    测试方法

    @Test
    public void getUserByName() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //返回结果是多条记录使用selectList
        List<User> userList = sqlSession.selectList("test.getUserByName", "%张三%");
        System.out.println(userList);
        sqlSession.close();
    }
    

    第二种方法

    Mapper文件

    <!-- 根据用户名查询用户 -->
    <!-- resultType是返回结果中一条记录的类型 -->
    <!-- ${}:字符串拼接指令。可以拼装成一个完整的sql语句。缺点不能防止sql注入
      ${}内部的名称,如果是简单数据类型,必须是value
      -->
    <select id="getUserByName" parameterType="string" resultType="cn.itcast.pojo.User">
        <!-- SELECT * from user where username LIKE #{name} -->
        SELECT * from user where username LIKE '%${value}%'
    </select>
    

    测试方法

    @Test
    public void getUserByName() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //返回结果是多条记录使用selectList
        //List<User> userList = sqlSession.selectList("test.getUserByName", "%张三%");
        List<User> userList = sqlSession.selectList("test.getUserByName", "张三");
        System.out.println(userList);
        sqlSession.close();
    }
    

    添加用户

    Sql语句

    INSERT INTO user`(username,birthday,sex,address) VALUES('','','','')

    Mapper文件

    <!-- 添加用户 -->
    <!-- 取对象中的属性直接使用#{}来取,括号中的名称必须是对象的属性名 -->
    <insert id="insertUser" parameterType="cn.itcast.pojo.User">
            INSERT INTO `user`(username,birthday,sex,address) 
            VALUES(#{username},#{birthday},#{sex},#{address})
    </insert>
    

    测试方法

    @Test
    public void insertUser() throws Exception {
            SqlSession sqlSession = sessionFactory.openSession();
            //添加用户
            User user = new User();
            user.setUsername("入云龙");
            user.setSex("1");
            user.setAddress("天津蓟县");
            user.setBirthday(new Date());
            sqlSession.insert("test.insertUser", user);
            sqlSession.commit();
            sqlSession.close();
    }
    

    主键返回

    在mysql中可以使用SELECT LAST_INSERT_ID();方法取当前事务中最后生成的id。在mybatis可以使用主键返回方法,把主键取出来返回给java程序。

    <!-- 添加用户 -->
        <!-- 取对象中的属性直接使用#{}来取,括号中的名称必须是对象的属性名 -->
        <insert id="insertUser" parameterType="cn.itcast.pojo.User">
            <!-- keyProperty:user对象的主键属性
                resultType:主键的数据类型
                order:取主键语句的执行时机。BEFORE:在插入之前执行     AFTER:插入之后执行
              -->
            <selectKey keyProperty="id" resultType="int" order="AFTER">
                <!-- mysql取主键的函数 -->
                SELECT LAST_INSERT_ID();
            </selectKey>
            INSERT INTO `user`(username,birthday,sex,address) 
            VALUES(#{username},#{birthday},#{sex},#{address})
        </insert>
    

    修改用户

    Sql语句

    UPDATE USER SET username = ' ', birthday= ' ', sex= ' ', address = '' WHERE id= 10

    Mapper文件

    <!-- 修改用户信息 -->
    <update id="updateUser" parameterType="cn.itcast.pojo.User">
        UPDATE USER
        SET username = #{username},
        birthday = #{birthday},
        sex = #{sex},
        address = #{address}
        WHERE
        id = #{id}
    </update>
    

    测试方法

    @Test
        public void updateUser() throws Exception {
            SqlSession sqlSession = sessionFactory.openSession();
            //取用户信息
            User user = sqlSession.selectOne("test.getUserById", 28);
            user.setUsername("武松");
            user.setAddress("清河县");
            sqlSession.update("test.updateUser", user);
            //提交修改
            sqlSession.commit();
            sqlSession.close();
        }
    
    

    删除用户

    Sql语句

    DELETE from user where id=10

    Mapper文件

    <!-- 删除用户 -->
    <delete id="deleteUserById" parameterType="int">
        DELETE from user where id=#{id}
    </delete>
    

    测试方法

    @Test
    public void deleteUserById() {
        SqlSession sqlSession = sessionFactory.openSession();
        sqlSession.delete("test.deleteUserById", 28);
        sqlSession.commit();
        sqlSession.close();
    }
    

    Mybatis和Hibernate的区别

    1. Mybatis并不是一个完全的orm框架。Hibernate是面向对象,可以不使用sql语句。Mybatis是面向sql语句的。专注的是输入映射返回值映射以及sql语句的灵活性。
    2. Mybatis门槛比较低,学习起来比较简单。查询性能,hibernate需要对性能进行优化,需要一个高手。Mybatis只需要对sql优化即可。
    3. Hibernate主要是应用在传统项目,开发速度很快。Mybatis主要用于互联网领域。适用于变化比较快的领域。
    4. 选择框架时,根据团队的技术储备。选择比较熟悉的框架。

    使用Mybatis开发dao的方法

    Sqlsession应用范围

    Sqlsession

    本身是线程不安全的,最佳应用范围应该是方法级别。

    SqlsessionFactory

    工厂类,创建Sqlsession的。此对象应该是单例模式出现在系统中,一个系统中只有一个SqlsessionFactory对象。

    SqlsessionFactoryBuilder

    当做一个工具类使用,创建完SqlsessionFactory对象就不用了。

    传统方式

    接口+实现类的方式

    Dao

    public class UserDaoImpl implements UserDao {
        
        private SqlSessionFactory sessionFactory;
        
        //构造方法中注入SqlSessionFactory对象。
        public UserDaoImpl(SqlSessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    
        @Override
        public User getUserById(int id) {
            
            SqlSession sqlSession = sessionFactory.openSession();
            User user = sqlSession.selectOne("test.getUserById", id);
            sqlSession.close();
            return user;
        }
    
        @Override
        public List<User> getUserByName(String name) {
            SqlSession sqlSession = sessionFactory.openSession();
            List<User> userList = sqlSession.selectList("test.getUserByName", name);
            sqlSession.close();
            return userList;
        }
    
        @Override
        public void insertUser(User user) {
            SqlSession sqlSession = sessionFactory.openSession();
            sqlSession.insert("test.insertUser", user);
            sqlSession.commit();
            sqlSession.close();
        }
    
    }
    

    测试方法

    public class UserDaoTest {
        
        private SqlSessionFactory sessionFactory;
        
        @Before
        public void init() throws Exception {
            // 创建一SqlSessionFactory
            // 把配置文件读取到流中
            InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
            // 创建SqlSessionFactory对象
            sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }
    
        @Test
        public void testGetUserById() {
            UserDao userDao = new UserDaoImpl(sessionFactory);
            User user = userDao.getUserById(10);
            System.out.println(user);
        }
    
        @Test
        public void testGetUserByName() {
            UserDao userDao = new UserDaoImpl(sessionFactory);
            List<User> list = userDao.getUserByName("张三");
            System.out.println(list);
        }
    
        @Test
        public void testInsertUser() {
            UserDao userDao = new UserDaoImpl(sessionFactory);
            User user = new User();
            user.setUsername("武大郎");
            user.setBirthday(new Date());
            user.setSex("1");
            user.setAddress("清河县");
            userDao.insertUser(user);
        }
    
    }
    

    存在的问题

    1. dao中操作数据库的代码重复。可以考虑使用模板替代。
    2. statementId存在硬编码的问题。

    使用Mapper代理的方法开发dao

    只写接口不写实现类

    开发规范

    1、mapper文件的命名规则推荐是“表名+Mapper.xml”。接口文件的名称和mapper映射文件的名称一致。
    2、Mapper文件的namespace必须是接口的全限定名。
    3、StatementID必须和接口中方法的名称一致。
    4、接口的参数类型必须和parameterType一致。
    5、接口的返回值类型必须和ResultType一致。

    代码实现

    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">
    <!-- namespace的作用就是sql语句隔离.
     如果使用Mapper代理形式开发,namespace必须是接口的全限定名-->
    <mapper namespace="cn.mapper.UserMapper">
        <!-- 
            select:如果是一个select语句就需要使用select节点。
            id就是一个sql语句的id,代表一个sql语句。起个名字叫做StatementId。
            parameterType:参数的类型
            resultType:返回结果的类型,可以是pojo类型,需要pojo的全限定名。
            #{}:是一个占位符。相当于jdbc中的“?”,括号内容的名称,如果是简单数据类型可以随便起。
         -->
        <select id="getUserById" parameterType="int" resultType="cn.itcast.pojo.User">
            SELECT * from user where id = #{id}
        </select>
    </mapper>
    

    接口:

    import cn.xx.pojo.User;
    
    public interface UserMapper{
        Uasr getUserById(int id);
    }
    

    SqlMapConfig.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>
        <!-- 和spring整合后 environments配置将废除 -->
        <environments default="development">
            <environment id="development">
                <!-- 使用jdbc事务管理 -->
                <transactionManager type="JDBC" />
                <!-- 数据库连接池 -->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver" />
                    <property name="url"
                        value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                    <property name="username" value="root" />
                    <property name="password" value="root" />
                </dataSource>
            </environment>
        </environments>
        <!-- 加载Mapper映射文件 -->
        <mappers>
            <!-- resource从classpath下开始查找 -->
            <mapper resource="sqlmap/user.xml" />
            <mapper resource="mapper/UserMapper.xml"/>
        </mappers>
    </configuration>
    

    测试方法

    @Test
    public void testGetUserById() {
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(10);
        System.out.println(user);
        sqlSession.close();
    }
    
    @Test
    public void testGetUserByName() {
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = userMapper.getUserByName("张三");
        System.out.println(list);
        sqlSession.close();
    }
    

    Mapper代理形式是官方推荐的使用方法。也是企业开发中最常用的方法。

    SqlMapConfig.xml

    配置内容

    SqlMapConfig.xml中配置的内容和顺序如下:

    properties(属性)

    settings(全局配置参数)

    typeAliases(类型别名)

    typeHandlers(类型处理器)

    objectFactory(对象工厂)

    plugins(插件)

    environments(环境集合属性对象)

    ​ environment(环境子属性对象)

    ​ transactionManager(事务管理)

    ​ dataSource(数据源)

    mappers(映射器)

    注意:Mybatis的配置文件配置项是有顺序的,不能打乱。

    Properties

    <!-- 属性配置 -->
    <!-- 可以使用resource加载外部配置文件 -->
    <properties resource="db.properties">
        <property name="JDBC_DRIVER" value="com.mysql.jdbc.Driver"/>
        <property name="JDBV_URL" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="JDBC_USER" value="root"/>
        <property name="JDBC_PASSWORD" value="root"/>
    </properties>
    

    如果同时使用的话,加载顺序是先加载内部的属性,然后再加载外部的属性。如果有重名的属性会覆盖。最终生效的是外部的属性文件。

    Settings

    Mybatis的全局属性配置

    <settings>
        <setting name="cacheEnabled" value="false"/>
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    

    配置项参见

    Setting(设置) Description(描述) Valid Values(验证值组) Default(默认值)
    cacheEnabled 在全局范围内启用或禁用缓存配置任何映射器在此配置下。 true | false TRUE
    lazyLoadingEnabled 在全局范围内启用或禁用延迟加载。禁用时,所有协会将热加载。 true | false TRUE
    aggressiveLazyLoading 启用时,有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则,每一个属性是按需加载。 true | false TRUE
    multipleResultSetsEnabled 允许或不允许从一个单独的语句(需要兼容的驱动程序)要返回多个结果集。 true | false TRUE
    useColumnLabel 使用列标签,而不是列名。在这方面,不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。 true | false TRUE
    useGeneratedKeys 允许JDBC支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用,如果设置为true,一些驱动会不兼容性,但仍然可以工作。 true | false FALSE
    autoMappingBehavior 指定MyBatis的应如何自动映射列到字段/属性。NONE自动映射。 PARTIAL只会自动映射结果没有嵌套结果映射定义里面。 FULL会自动映射的结果映射任何复杂的(包含嵌套或其他)。 NONE, PARTIAL, FULL PARTIAL
    defaultExecutorType 配置默认执行人。SIMPLE执行人确实没有什么特别的。 REUSE执行器重用准备好的语句。 BATCH执行器重用语句和批处理更新。 SIMPLE REUSE BATCH SIMPLE
    defaultStatementTimeout 设置驱动程序等待一个数据库响应的秒数。 Any positive integer Not Set (null)
    safeRowBoundsEnabled 允许使用嵌套的语句RowBounds。 true | false FALSE
    mapUnderscoreToCamelCase 从经典的数据库列名A_COLUMN启用自动映射到骆驼标识的经典的Java属性名aColumn。 true | false FALSE
    localCacheScope MyBatis的使用本地缓存,以防止循环引用,并加快反复嵌套查询。默认情况下(SESSION)会话期间执行的所有查询缓存。如果localCacheScope=STATMENT本地会话将被用于语句的执行,只是没有将数据共享之间的两个不同的调用相同的SqlSession。 SESSION | STATEMENT SESSION
    dbcTypeForNull 指定为空值时,没有特定的JDBC类型的参数的JDBC类型。有些驱动需要指定列的JDBC类型,但其他像NULL,VARCHAR或OTHER的工作与通用值。 JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER OTHER
    lazyLoadTriggerMethods 指定触发延迟加载的对象的方法。 A method name list separated by commas equals,clone,hashCode,toString
    defaultScriptingLanguage 指定所使用的语言默认为动态SQL生成。 A type alias or fully qualified class name. org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver
    callSettersOnNulls 指定如果setter方法或地图的put方法时,将调用检索到的值是null。它是有用的,当你依靠Map.keySet()或null初始化。注意原语(如整型,布尔等)不会被设置为null。 true | false FALSE
    logPrefix 指定的前缀字串,MyBatis将会增加记录器的名称。 Any String Not set
    logImpl 指定MyBatis的日志实现使用。如果此设置是不存在的记录的实施将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING Not set
    proxyFactory 指定代理工具,MyBatis将会使用创建懒加载能力的对象。 CGLIB | JAVASSIST

    typeAliases

    别名配置

    Mybatis中定义的别名

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

    自定义别名

    <!-- 别名配置 -->
    <typeAliases>
            <!-- type:类的全限定名
                alias:别名
                别名不区分大小写
             -->
            <!-- <typeAlias type="cn.itcast.pojo.User" alias="user"/> -->
            <!-- 可以使用package批量定义别名,name属性就是pojo类所在的包名的全限定名
                别名就是类名,不区分大小写。
             -->
        <package name="cn.itcast.pojo"/>
    </typeAliases>
    

    Mappers

    加载Mapper映射文件

    <!-- 加载Mapper映射文件 -->
        <mappers>
            <!-- resource从classpath下开始查找 -->
            <mapper resource="sqlmap/user.xml"/>
            <!-- <mapper resource="mapper/UserMapper.xml"/> -->
            <!-- url配置的是文件的全路径 -->
            <!-- <mapper url="file:///D:\传智播客\10.课堂笔记\0413\mybatis\day01\source\MybatisSecond0413\config\mapper\UserMapper.xml"/> -->
            <!-- class指定接口的全限定名,要求Mapper映射文件和接口在同一个目录下,且名称相同。 -->
            <!-- <mapper class="cn.itcast.mapper.UserMapper"/> -->
            <!-- mapper接口所在包的全限定名,mybatis会扫描包下的接口,加载和接口同名的mapper映射文件 -->
            <package name="cn.itcast.mapper"/>
        </mappers>
    
    

    Mapper映射文件

    输入参数映射

    基础数据类型

    Integer、String、float等

    POJO类型参数

    例如添加用户、修改用户时使用user对象作为参数

    POJO的包装类型

    POJO中有一个属性,类型是POJO。

    使用场合:查询条件复杂的时候,可以使用POJO的包装类型

    QueryVo

    ​ |-user

    ​ |-item

    创建一个QueryVo

    package cn.itcast.pojo;
    
    public class QueryVo {
    
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
        
    }
    

    使用QueryVo查询

    需求:根据用户id查询用户信息

    QueryVo

    ​ |-User

    ​ |-id

    Sql语句:select * from user where id=1

    Mapper文件:

    <select id="getUserByQueryVo" parameterType="QueryVo" resultType="user">
            <!-- 取属性名称使用“.”的方式来取 -->
            select * from user where id=#{user.id}
    </select>
    

    接口定义:

    public interface UserMapper{
        User getUserByQueryVo(User user);   
    }
    

    测试方法:

    @Test
    public void testGetUserByQueryVo() {
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //创建一个QueryVo对象
        QueryVo queryVo = new QueryVo();
        //创建一个user对象
        User user = new User();
        user.setId(10);
        queryVo.setUser(user);
            
        User userResult = userMapper.getUserByQueryVo(queryVo);
        System.out.println(userResult);
            
        sqlSession.close();
    }
    

    Map类型

    使用map作为参数进行映射。Map是key-value形式。绑定的时候应该使用#{key}。

    返回值映射

    返回基础数据类型

    返回值是一个int或者String

    Sql语句

    select count(*) from user

    Mapper 文件

    <!-- 查询用户数量 -->
    <select id="getUserCount" resultType="int">
        select count(*) from user
    </select>
    

    方法定义

    public interface UserMapper {
        int getUserCount();
    }
    

    测试方法

    @Test
    public void testGetUserCount() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int count = userMapper.getUserCount();
        System.out.println(count);
        sqlSession.close();
    }
    

    要求sql语句的查询结果必须是一条记录,可以是多个列,多个列的情况下只取第一列的内容返回。

    POJO类型的返回结果

    根据用户id查询用户信息。返回一个user对象就是一个pojo。

    POJO的List结果

    根据用户名查询用户信息返回一个用户列表就是一个pojoList。

    返回一个Map类型

    Pojo要求返回的结果中列名和pojo的属性名要一致。

    如果返回结果是map类型,那么key就是列名,value就是就是此列的值。

    Pojo属性名和列名不一致

    1. 修改sql语句,使用别名保证结果集中的列名和pojo的属性名一致。
    2. 使用ResultMap

    ResultMap入门

    resultMap定义

    <!-- resultMap的定义 -->
    <!-- type:接收返回结果的数据类型,此处为user -->
    <resultMap type="user" id="userResultMap">
        <!-- 
         id:为主键列
         column:结果集中的主键列的列名
         property:对应user对象中保存主键属性。
         -->
        <id column="id" property="id"/>
        <!-- 普通列 -->
        <result column="uname" property="username"/>
        <result column="bday" property="birthday"/>
        <result column="sex" property="sex"/>
        <result column="addr" property="address"/>
    </resultMap>
    <!-- resultMap属性指定一个resultMap的id -->
    <select id="getUserResultMap" resultMap="userResultMap">
        select id, username uname, birthday bday, sex, address addr from user
    </select>
    

    接口定义

    public interface UserMapper{
        List<User> getUserResultMap();
    }
    

    测试方法

    @Test
    public void testGetUserResultMap() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = userMapper.getUserResultMap();
        System.out.println(list);
        sqlSession.close();
    }
    

    动态sql

    If

    需求:根据参数的不同调整查询条件

    Mapper文件

    <select id="getUserList" parameterType="user" resultType="user">
        select * from user
        where 0=0
        <if test="id!=null and id != 0">
            and id = #{id}
        </if>
        <if test="username != null and username != '' ">
            and username like '%${username}%'
        </if>
    </select>
    

    接口定义

    public interface UserMapper{
        List<User> getUserList(User user);
    }
    

    测试方法

    @Test
    public void testGetUserList() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //创建user对象作为查询条件
        User user = new User();
        user.setId(1);
        user.setUsername("张三");
        List<User> userList = userMapper.getUserList(user);
        System.out.println(userList);
        sqlSession.close();
    }
    

    Where

    可以根据条件动态的添加where关键字,并且可以去掉多余的and

    <select id="geUserList" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="id != null and id != 0">
                and id = #{id}
            </if>
            <if test="username != null and username != ''">
                and username like '%${username}%'
            </if>
        </where>
    </select>
    

    Foreach

    创建QueryVo对象

    public class QueryVo {
        private User user;
        private int[] ids;
        //省略get和set方法
    }
    

    Mapper文件

    <select id="getUserList" parameterType="QueryVo" resultType="user">
            select * from user
            <where>
                <if test="user!=null">
                    <if test="user.id!=null and user.id != 0">
                        and id = #{user.id}
                    </if>
                    <if test="user.username != null and user.username != '' ">
                        and username like '%${user.username}%'
                    </if>
                </if>
                <if test="ids!=null">
                    <!-- 
                    collection:QueryVo中的集合属性ids
                    open:前缀
                    close:后缀
                    item:循环的变量名称
                    separator:分隔符
                     -->
                    <foreach collection="ids" open="and id in(" close=")" item="id" separator=",">
                        #{id}
                    </foreach>
                </if>
            </where>
    </select>
    

    接口定义

    public interface UserMapper{
        List<User> getUserList(QueryVo queryVo);
    }
    

    测试方法

    @Test
    public void testGetUserList() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //创建user对象作为查询条件
        User user = new User();
        //user.setId(1);
        //user.setUsername("张三");
        QueryVo queryVo = new QueryVo();
        queryVo.setUser(user);
        int[] ids = {1,10,16,22,24};
        queryVo.setIds(ids);
        List<User> userList = userMapper.getUserList(queryVo);
        System.out.println(userList);
        sqlSession.close();
    }
    

    相关文章

      网友评论

        本文标题:Mybatis--day01

        本文链接:https://www.haomeiwen.com/subject/mnwogttx.html