Mybatis的CRUD与高级查询操作

Mybatis是一个半自动化的ORM持久化框架,可以通过简单的XML或注解用与配置或原始映射,将接口和POJO对象映射成数据库中的记录


Mybatis整体架构:
    1、    配置文件
    全局配置文件:mybatis-config.xml作用:配置数据源,引入映射文件
    映射文件:XxMapper.xml作用:配置sql语句、参数、结果集封装类型等
    2、    SqlSessionFactory
    作用:获取SqlSession
    通过newSqlSessionFactoryBuilder().build(inputStream)来构建,inputStream:读取配置文件的IO流
    3、    SqlSession
    作用:执行CRUD操作
    它是线程不安全的。因此最佳的使用范围是请求或方法范围。
    4、    Executor
    执行器,SqlSession通过调用它来完成具体的CRUD
    它是一个接口,提供了两种实现:缓存的实现、数据库的实现
    5、    Mapped Statement
    在映射文件里面配置,包含3部分内容:
    具体的sql,sql执行所需的参数类型,sql执行结果的封装类型
    参数类型和结果集封装类型包括3种:
    HashMap,基本数据类型,pojo
    
约束配置:可以通过快捷键获取xml中的所有标签
        Preferences------>XML Catalog
        添加两个约束:
            全局配置文件的约束: http://mybatis.org/dtd/mybatis-3-config.dtd
            映射文件的约束:     http://mybatis.org/dtd/mybatis-3-mapper.dtd
    
    
全局配置文件:mybatis-config
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 引入外部资源文件
        resource:默认引入classpath路径下的资源文件
     -->
    <properties resource="jdbc.properties"></properties>

    <!-- 设置驼峰匹配:从数据库列名映射java属性名称的经典方式 -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!-- 配置别名 -->
    <typeAliases>
        <!-- typeAlias:用来配置别名,方便映射文件使用,type:类的全限定类名,alias:别名 -->
        <!-- <typeAlias type="cn.itcast.pojo.User" alias="User"/> -->
        <!-- 配置包扫描:解决多个pojo别名问题,默认将类名作为笔名,大小写不敏感 -->
        <package name="cn.itcast.pojo"/>
    </typeAliases>

    <!-- 配置环境:可以配置多个环境,default:配置某一个环境的唯一标识,表示默认使用哪个环境 -->
      <environments default="development">
        <!-- 配置环境,id:环境的唯一标识 -->
        <environment id="development">
        <!-- 事务管理器,type:使用jdbc的事务管理器 -->
          <transactionManager type="JDBC"/>
          <!-- 数据源,type:数据源类型,池类型的数据源 -->
          <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>
  <!-- 配置映射文件:用来配置sql语句和结果集类型等 -->
  <mappers>
    <mapper resource="UserMapper.xml"/>
  </mappers>
</configuration>


映射文件配置:XxMapper.xml
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
    mapper标签:配置各类声明
    namespace:名称空间,由于映射文件有多个,为了防止crud语句的唯一标识被重复,可以设置空间名称。
    cn.itcast.mapper.UserMapper  :  对数据库CRUD操作的接口方法类似于IUserDao
    名称空间必须改成UserMapper接口的全路径,StatementId必须和接口方法名一致,结果集的封装类型已经和方法的返回类型一致
 -->
<mapper namespace="cn.itcast.mapper.UserMapper">
    <!—
        
        select:查询的statement(声明),用来编写查询语句
        id:语句的唯一标识
        resultType:配置返回的结果集类型
     -->
  <select id="queryUserById" resultType="User">
    select * from tb_user where id = #{id}
  </select>
</mapper>


测试类:
private UserMapper userMapper;
    //获取全局配置文件输入流
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    //加载全局配置文件
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //获取sqlSession并自动提交事务
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
    //通过动态代理生成一个代理的实现类
    userMapper = sqlSession.getMapper(UserMapper.class);
    

    public void testQueryUserById() {
        User user = userMapper.queryUserById(1L);
        System.out.println(user);
    }

    
全局配置文件:mybatis-config 标签总结:
    Properties:引入外部资源文件


    Settings:配置驼峰命名方式,类似经典的数据库字段名和java类中属性的映射关系。

    typeAliases:配置别名


    typeHandler:类型转换器

    plugings:插件,又称之为拦截器(分页助手、通用mapper)


    environments:可以配置多个环境
        environment:配置环境
            transactionManager:配置事务管理器
            dataSource:配置数据源
        

    mappers:配置映射文件
    Package:通过包名配置映射文件

映射文件配置:XxMapper.xml 标签详解:

Select标签:用来编写查询语句的statement
    id属性:唯一标识
    resultType:查询语句返回的结果集类型
    parameterType:参数类型,使用动态代理之后,需要和mapper接口中的参数类型一致,可以省略。

Insert标签:编写新增语句的statement
    insert:编写插入语句
          id:插入语句的唯一标识
          parameterType:插入语句的参数类型,使用动态代理之后,需要和mapper接口中的参数类型一致,可以省略。
          useGeneratedKeys:开启主键自增回显,将自增长的主键值回显到形参中(即封装到User对象中)
          keyColumn:数据库中主键的字段名称
          keyProperty:pojo中主键对应的属性

Update标签:编写更新语句的statement
    id:语句的唯一标识
      parameterType:语句的参数类型,使用动态代理之后,需要和mapper接口中的参数类型一致,可以省略。

delete标签:编写删除语句的statement
    id:语句的唯一标识
      parameterType:语句的参数类型,使用动态代理之后,需要和mapper接口中的参数类型一致,可以省略。

    
CRUD标签都有一个属性parameterType,statement通过它指定接收的参数类型。
接收参数的方式有两种:
    1、    #{}预编译(传入的值会加"")
    2、${}非预编译(直接的sql拼接,不能防止sql注入)
    参数类型有三种:
    1、    基本数据类型
    2、    HashMap(使用方式和pojo类似)
    3、    Pojo自定义包装类型
    
    使用@Param注解指定参数名:@Param("userName")String userName,然后再在statement中调用#{userName}或${userName}

ResultMap是mybatis中最重要最强大的元素,使用ResultMap可以解决两大问题:
    1. POJO属性名和表结构字段名不一致的问题(有些情况下也不是标准的驼峰格式,比如id和userId)
    2. 完成高级查询,比如说,一对一、一对多、多对多.

一:配置resultMap
    <!--
        resultMap标签:可以自己配置对象属性和表字段的映射(不仅仅是驼峰规则的映射)
        type属性:结果集的封装类型
        id属性:唯一标识
        autoMapping属性:如果不配置,默认为true。对其他属性进行自动映射。
     -->
    <resultMap type="User" id="userResultMap" autoMapping="true">
        <!-- id标签:配置主键映射,column:表中的字段名称,property:属性名称 -->
        <id column="id" property="id"/>
        <!-- 可以用来配置普通类型字段和属性映射(非复杂类型) -->
        <result column="user_name" property="userName"/>
    </resultMap>
二:将statement中的resultType属性改为    resultMap:userResultMap
问题:
    字段和属性名称都匹配的字段要不要配置?
    这个取决于resultMap中的autoMapping属性的值:
    为true时:resultMap中的没有配置的字段会自动对应。如果不配置,则默认为true。
    为false时:只针对resultMap中已经配置的字段作映射。

将重复的sql片段抽取为一个xml配置文件:
    一:新建一个xml文件CommonSql.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">
          <mapper namespace="CommonSQL">
          
            <sql id="commonSql">
                id,
                user_name,
                password,
                name,
                age,
                sex,
                birthday,
                created,
                updated
            </sql>
          </mapper>
    
    二:引入全局配置
        <mapper resource="CommonSql.xml" />
    
    三:最后在需要使用该sql片段的地方通过include标签的refId属性引用该sql片段:<include refId="CommonSql.commonSql" />
        refId=名称空间.sql片段的id
        
动态sql:
    1、if
    2、choose when otherwise
        choose标签:条件选择
            when子标签:编写条件,不管有多少个when条件,一旦其中一个条件成立,后面的when条件都不执行。
            test属性:编写ognl表达式
        otherwise子标签:当所有条件都不满足时,才会执行该条件。
    3、where标签
        可以自动将动态sql中多出来的一个and或者or去除。
    4、set标签:
        可以用在update的statement中,自动添加一个set关键字,并且会将动态sql最后多余的逗号去除。
    5、foreach标签:遍历集合
        collection属性:接收的集合参数
        item属性:集合参数中的每一个元素
        separator属性:标签逗号分隔符
        open属性:以什么开始
        close属性:以什么结束

mybatis的缓存机制:
    一级缓存:一级缓存默认是开启的(不管你用或不用,她一直都在),作用域:在同一个sqlSession下
    二级缓存:
        1、    同一个mapper的namespace,在同一个namespace中查询sql可以从缓存中命中。
        2、    跨sqlSession,不同的SqlSession可以从二级缓存中命中
        
高级查询:
    注意:一旦涉及到嵌套映射,一定要设置手动设置为自动映射。不管是Order的自动映射还是User的自动映射都需要手动设置为true。
    resultMap中的数据其他地方也要用到,那么可以使用继承的方法来复用即可 extends="orderUserMap"
一对一:
    <resultMap type="Order" id="orderUserMap" autoMapping="true">
        <id property="id" column="id"/>
        <!--
            association:用于对一的映射
            property:类中的关联属性的名称
            javaType:属性对应的类型
            autoMapping:添加自动映射,一旦涉及到嵌套查询,需要手动设置为true
         -->
        <association property="user" javaType="User" autoMapping="true">
            <!--
                id:关联对象的主键
                property:关联对象的主键名称
                column:关联对象在表中对应的字段名称,如果重名,可以使用别名
             -->
            <id property="id" column="uid"/>
        </association>
    </resultMap>

一对多:
    <resultMap type="Order" id="orderUserMap" autoMapping="true" extends="orderUserMap">
        <collection property="detailList" javaType="List" ofType="Orderdetail" autoMapping="true">
            <!--
                property:类中的对应主键的属性名称
                column:表中的字段名称,可以使用自己在sql语句中设置的别名,注意不要使用结果中有mysql自动设置的别名,如id2
             -->
            <id property="id" column="detail_id"/>
        </collection>
    </resultMap>

多对多:
    <resultMap type="Order" id="orderUserMap" autoMapping="true" extends="orderUserMap">
    <collection property="detailList" javaType="List" ofType="Orderdetail">
            <!--
                property="id":关联对象的主键的属性名称
                column:关联对象在表中的主键名称,如果重复,可以使用别名
             -->
            <id property="id" column="detail_id"/>
                <!-- 通过Orderdetail对一查询Item -->
                <association property="item" javaType="Item" autoMapping="true">
                    <!--
                        property:item的主键的属性名称
                        column:表中主键的字段名称,如果重名,可以使用别名,或者外键名称
                     -->
                    <id property="id" column="iid"/>
                </association>
        </collection>
    </resultMap>

延迟加载:
    一:两个statement就分别相当于两条查询order和查询user的sql语句,然后通过resultMap将延迟加载的查询user的statement关联到查询查询order的statement上。使得在查询order之后,
        <resultMap type="Order" id="orderUserLazyMap" autoMapping="true">
            <id property="id" column="id"/>
            <!-- 关联查询user
                select:延迟加载user,通过调用另外的user的statement来发送第二个语句查询user
                column:查询user的参数,该id的信息其实是在查询出来的order中的user_id
                       如果参数有多个,可以使用{user_id=id,user_name = userName}的方式来传参
            -->
            <association property="user" javaType="User" select="queryUserByUserIdOfOrder" column="user_id"></association>
        </resultMap>

        <!-- 通过order_number查询order -->
        <select id="queryOrderUserLazy" resultMap="orderUserLazyMap">
            select * from tb_order where order_number = #{orderNumber}
        </select>
        
        <!-- 通过order中的user_id查询user -->
        <select id="queryUserByUserIdOfOrder" resultType="User">
            select * from tb_user where id = #{id}
        </select>

    二:开启延迟加载开关
        <settings>
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="aggressiveLazyLoading" value="false"/>
        </settings>

    
    三:添加cglib的依赖
        <!-- cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.1</version>
        </dependency>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值