mybatis基础知识——学习笔记(2)

来源:互联网 发布:激活码网站源码 编辑:程序博客网 时间:2024/05/16 10:07
1.1 SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理,在需要创建SqlSessionFactory的时候,只需要new一次SqlSessionBuilder。

1.2 SqlSessionFactory
通过SqlSessionFactory创建SqlSession,使用单例模式管理SqlSessionFactory(工厂一旦创建使用一个实例)
mybatis和spring整合后,使用单例模式管理sqlSessionFactory

1.3 SqlSession
SqlSession是一个面向用户(程序员)的接口
SqlSession中提供了很多操作数据库的方法,如:selectOne、selectList
SqlSession是线程不安全的,在SqlSession实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性
SqlSession最佳应用场合在方法体类,定义成局部变量使用

2.2 原始Dao层开发方法
需要写dao接口和dao实现类,需要向dao实现类中注入SqlSessionFactory创建Sqlsession

接口实现类:
private SqlSessionFactory sqlSessionFactory;
    
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
    
    @Override
    public User findUserById(int id) throws Exception {
        // TODO Auto-generated method stub
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById", id);
        sqlSession.close();
        return user;
    }

    @Override
    public List<User> findUserByName(String username) throws Exception {
        // TODO Auto-generated method stub
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession.selectList("test.findUserByName",username);
        sqlSession.close();
        return list;
    }

    @Override
    public void deleteUser(int id) throws Exception {
        // TODO Auto-generated method stub
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("test.deleteUser", id);
        sqlSession.commit();
        sqlSession.close();
        

    }


开发问题:  a.dao接口实现类中存在大量的模版方法
            b.调用sqlSession方法时将statement的id硬编码了
            c.调用sqlSession方法时传入的变量,由于sqlSession是泛型,即使变量类型传入错误,在编译阶段也不会报错,不利于开发

2.3 mapper代理方法
需要mapper接口,相当于dao接口,
还需要编写mapper映射文件,遵循开发规范,mybaties则可以自动生成mapper接口实现代理对象

规范:
a.namespace等于mapper接口的地址
b.mapper.java接口中的方法名和mapper.xml中statement的id一致
c.mapper.java接口中的输入参数类型和mapper.xml中指定类型一致
d.mapper.java接口中返回值和mapper.xml中指定返回类型一致

使用mapper代理:
public void testFindUserById() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //创建UserMapper对象,mybatis自动生成mapper代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用userMapper方法
        User user = userMapper.findUserById(2);
        System.out.println(user);
    }

增加了映射文件需要在SqlMapConfig.xml中配置

3.1 SqlMapConfig.xml
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
    environment(环境子属性对象)
        transactionManager(事务管理)
        dataSource(数据源)
mappers(映射器)

3.2 properties属性
需求:将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig中加载db.properties的属性值,在SqlMapConfig中不用对数据库连接参数硬编码。

将数据库连接参数只配置在db.properties中的原因:方便对参数进行统一管理,其他xml文件可以引用db.properties
配置:
<configuration>
    <properties resource="db.properties"></properties>
    <!-- 和spring整合后 environment配置将废除 -->
    <environments default="development">
    <!-- 使用JDBC事务管理 -->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers >
    <!-- 加载映射文件 -->
        <mapper resource="sqlMap/UserMapper.xml"></mapper>
    </mappers>
</configuration>

注意:Mybatis将按照下面的顺序加载属性
1.在properties元素体内定义的属性首先被读取
2.然后会读取properties元素中resource或url加载的属性,会覆盖已读取的同名属性
3.最后读取parameterType传递的属性,会覆盖已读取的同名属性

因此,parameterType传递的属性具有最高优先级,#{name}传入的参数会覆盖之前的name属性
建议:不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中,在properties文件中定义属性名要有一定的特殊性,如xxx.xxxx.xxx

3.3 setting全局参数配置
mybaties在运行时可以调整一些运行参数,如:开启二级缓存、开启延迟加载
全局参数会影响mybatis的运行行为

3.4 typeAliases别名
需求:在mapper.xml中定义了很多的statement,statement需要parameterType和resultType指定输入输出类型。如果在指定类型时输入类型的全路径,不便进行开发,可以针对输入输出参数定义一些别名。

mybaties默认支持别名,针对pojo需要自定义别名
配置:
    <typeAliases>
        <!-- 单个别名定义 -->
        <typeAlias type="mybatis.po.User" alias="user"/>
        <!-- 批量定义别名
        指定报名,自动扫描包中的pojo类,自动定义别名,别名为类名,首字母可大写可小写 -->
        <package name="mybatis.po"/>
    </typeAliases>
    
3.5 typeHandlers类型处理器
mybatis中通过typeHandlers完成jdbc类型和java类似的转换
通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义

3.5 mappers
    <mappers >
    <!-- 加载映射文件 -->
        <!-- 通过resource加载单个映射文件 -->
        <mapper resource="sqlMap/UserMapper.xml"></mapper>
        <!-- 通过mapper接口加载映射文件,需要将mapper接口类名和mapper.xml映射文件名称保持一致,并且在一个目录中
        以上条件前提,使用mapper代理的方法 -->
        <mapper class="mybatis.dao.UserMapper"></mapper>
        <!-- 批量加载mapper 指定mapper接口的包名,自动扫描包中所有mapper进行加载
        需要将mapper接口类名和mapper.xml映射文件名称保持一致,并且在一个目录中
        以上条件前提,使用mapper代理的方法
         -->
        <package name="mybatis.dao"/>
    </mappers>

推荐使用批量加载

3.6 输入映射(传递pojo的包装对象)

需求:完成用户信息的综合查询,需要传入很多查询条件(可能包括用户信息、商品信息、订单信息)
使用自定义包装类型的pojo,包装自己需要的复杂查询条件

在UserMapper.xml中定义用户信息综合查询(查询条件复杂,通过高级查询进行复杂关联查询)

3.7 输出映射

3.7.1 resultType

使用resultType进行映射,只有查询出来的列名和pojo的属性名一致,该列才可以映射成功
如果查询出来的列名和pojo的属性名完全不一致,则没有创建pojo对象
只要查询出来的列名和pojo的属性名有一个一致,就会创建pojo对象


3.7.2 resultMap
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和属性名之间作一个映射关系
配置:    
    <!-- type result最终映射成的java对象类型,可以使用别名
    id 对resultMap的唯一表示 -->
    <resultMap type="user" id="userResultMap">
        <!-- id查询结果集中的唯一标识
        column :查询出来的别名
        property:type指定的pojo类型中的属性名
        最终resultMap对column和property作一个映射关系 -->
        <id column="id_" property="id"/>
        <!-- result:对普通列名映射定义 -->
        <result column="username_" property="username"/>
        
    </resultMap>
        

4 动态sql

4.1 什么是动态sql

mybatis核心,对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装

4.2 if判断

    <select id="findUserList" parameterType="mybatis.po.User" resultType="mybatis.po.User">
        select * from users
        <where>
        <!-- where自动去掉条件中的第一个and -->
            
                <if test="id!=null and id!=''">
                    and id=#{id}
                </if>
                <if test="username!=null and username!=''">
                    and username like #{username}
                </if>
            
        </where>
    </select>

4.3 sql片段
将实现动态sql片段的代码抽取出来,组成一个sql片段,其他statement中可以引用该sql片段
配置:
<!-- id:sql片段的唯一标识
    是基于单表来定义的sql片段,这样可重用性高
    在sql片段中不要包含where -->
    <sql id="query_user_where">
        
            
                <if test="id!=null and id!=''">
                    and id=#{id}
                </if>
                <if test="username!=null and username!=''">
                    and username like #{username}
                </if>
    </sql>

引用:<select id="findUserList" parameterType="mybatis.po.User" resultType="mybatis.po.User">
        select * from users
        <where>
        <!-- where自动去掉条件中的第一个and -->
            <include refid="query_user_where"></include>
            <!-- 引用的id不在本mapper中,需要在前面加namespace -->
        </where>
    </select>
    
    
4.4 foreach
向sql传递数组或list,使用foreach解析

配置: <!-- 使用foreach遍历传入ids
            collection:指定输入对象中集合属性
            item:每个遍历生成对象
            open:开始遍历时拼接的串
            close:结束遍历时拼接的串
            separator:遍历的两个对象之间需要拼接的串 -->
            <if test="ids!=null">
            <!-- 实现以下sql拼接: AND (id=1 OR id=2 OR id=3) -->
                <foreach collection="ids" item="id" open="AND (" close=")" separator="OR" ></foreach>
            </if>

0 0
原创粉丝点击