美文网首页
MyBatis记错本

MyBatis记错本

作者: 值得_e36c | 来源:发表于2019-02-18 16:19 被阅读0次

    1.第一个简单的MyBatis程序

    1.personMapper.xml image.png
    2.config.xml image.png
    3.main方法

    2. image.png

    default可以选择用下面的哪个数据库连接,可以写多个environment标签


    上图的地方可以修改development

    3.

    POOLED代表使用数据库连接池,UNPOOLED代表不使用数据库连接池,即传统的JDBC方式

    4. image.png

    一个联网的才能找到的文件,可以下载下来导入,那样不联网也会有提示信息。

    5.

    6.两种方式的增删改查

    1.基础方式的增删改查CRUD

    2.mapper动态代理方式的CRUD(MyBatis接口开发)
    原则:约定优于配置

    约定的目标:省略掉statement

    7.优化

    1.可以将配置信息 单独放入 db.properties文件中,然后再动态引入
     db.properties:
        k=v
    
    <configuration>
        <properties  resource="db.properties"/>
    

    引入之后,使用${key}

    2.MyBatis全局参数

    在conf.xml中设置

        <settings>
                <setting name="cacheEnabled" value="false"  />
                <setting name="lazyLoadingEnabled" value="false"  />
        </settings>
    
    3.别名 conf.xml

    a.设置单个别名

    b.批量设置别名

    <typeAliases>
        <!-- 单个别名 (别名 忽略大小写) -->
        <!-- <typeAlias type="org.lanqiao.entity.Student" alias="student"/> -->
        <!--  批量定义别名  (别名 忽略大小写),以下会自动将该包中的所有类 批量定义别名: 别名就是类名(不带包名,忽略大小写)   -->
        <package name="org.lanqiao.entity"/>
    </typeAliases>
    

    除了自定义别名外,MyBatis还内置了一些常见类的别名。

    4.类型处理器(类型转换器)

    1.MyBatis自带一些常见的类型处理器
    int - number

    2.自定义MyBatis类型处理器

    java -数据库(jdbc类型)
    

    示例:

    实体类Student :  boolean   stuSex      
                true:男
                false:女
    
    表student:   number  stuSex
                1:男
                0:女
    

    自定义类型转换器(boolean -number)步骤:
    a.创建转换器:需要实现TypeHandler接口
    通过阅读源码发现,此接口有一个实现类 BaseTypeHandler ,因此 要实现转换器有2种选择:
    i.实现接口TypeHandler接口
    ii.继承BaseTypeHandler

    b.配置conf.xml image.png

    需要注意的问题: INTEGER

    insert into student(stuno,stuname,stuage,graname,stusex) values(#{stuNo},#{stuName},#{stuAge},#{graName} ,#{stuSex ,javaType=boolean  ,jdbcType=INTEGER   } ) 
    

    注意#{stuNo} 中存放的是 属性值,需要严格区分大小写。

    5.resultMap可以实现2个功能:

    1.类型转换
    2.属性-字段的映射关系

    <select id="queryStudentByStuno"    parameterType="int"     resultMap="studentMapping" >
            select * from student where stuno = #{stuno}
    </select>
        
        <resultMap type="student" id="studentMapping">
                <!-- 分为主键id 和非主键 result-->
                <id property="id"  column="stuno"  />
                <result property="stuName"  column="stuname" />
                <result property="stuAge"  column="stuage" />
                <result property="graName"  column="graname" />
                <result property="stuSex"  column="stusex"  javaType="boolean" jdbcType="INTEGER"/>
        
        
        </resultMap>
    

    8.输入参数:parameterType

    1.类型为 简单类型(8个基本类型+String)

    #{}、${}的区别
    a.

    #{任意值}
    ${value} ,其中的标识符只能是value

    b.

    #{}自动给String类型加上'' (自动类型转换)

    ${} 原样输出,但是适合于 动态排序(动态字段)

    select stuno,stuname,stuage  from student where stuname = #{value}
    
    select stuno,stuname,stuage  from student where stuname = '${value}'
    
    动态排序:
    select stuno,stuname,stuage  from student  order by ${value} asc
    

    c.#{}可以防止SQL注入
    ${}不防止

    ${}、#{}相同之处:
    a.都可以 获取对象的值 (嵌套类型对象)

    i.获取对象值:
    模糊查询,方式一:

    select stuno,stuname,stuage  from student where stuage= #{stuAge}  or stuname like #{stuName} 
                Student student = new Student();
                student.setStuAge(24);
                student.setStuName("%w%");
                List<Student> students = studentMapper.queryStudentBystuageOrstuName(student) ;//接口的方法->SQL
    

    模糊查询,方式二:

        student.setStuName("w");
        select stuno,stuname,stuage  from student where stuage= #{stuAge}  or stuname like '%${stuName}%
    
    ii.嵌套类型对象 通过级联获得

    9.输入对象为HashMap:

    where stuage= #{stuAge}
    用map中key的值 匹配 占位符#{stuAge},如果匹配成功 就用map的value替换占位符

    10.mybatis调用存储过程

    <select id="queryCountByGradeWithProcedure" statementType="CALLABLE"  parameterType="HashMap" >
        {
            CALL queryCountByGradeWithProcedure(
                #{gName,jdbcType=VARCHAR,mode=IN},
                #{scount,jdbcType=INTEGER,mode=OUT}
            ) 
        }   
    </select>
    

    其中 通过statementType="CALLABLE"设置SQL的执行方式是存储过程。 存储过程的输入参数gName需要通过HashMap来指定
    在使用时,通过hashmap的put方法传入输入参数的值;通过hashmap的Get方法 获取输出参数的值。
    要注意Jar问题:ojdbc6.jar不能在 调存储过程时 打回车、tab,但是ojdbc7.jar可以。

    如果报错: No enum constant org.apache.ibatis.type.JdbcType.xx,则说明mybatis不支持xx类型,需要查表。

    存储过程 无论输入参数是什么值,语法上都需要 用map来传递该值;

    只要 是 <transactionManager type="JDBC" />,则增删改都需要手工commit ;

    11.输出参数resultType

    1.简单类型(8个基本+String)
    2.输出参数为实体对象类型
    3.输出参数为实体对象类型的集合 :虽然输出类型为集合,但是resultType依然写 集合的元素类型(resyltType="Student")
    4.输出参数类型为HashMap
    --HashMap本身是一个集合,可以存放多个元素,
    但是根据提示发现 返回值为HashMap时 ,查询的结果只能是1个学生(no,name);
    -->结论:一个HashMap 对应一个学生的多个元素(多个属性) 【一个map,一个学生】

    二维数组
    {
    {1,zs,23,xa}, -一个HashMap对象
    {2,ls,24,bj},
    {3,ww,25,tj}
    }

    resultType
    resultMap:实体类的属性、数据表的字段: 类型、名字不同时(stuno,id)
    注意:当属性名 和字段名 不一致时,除了使用resultMap以外,还可以使用resultType+HashMap:

    a.resultMap
    <resultMap type="student" id="queryStudentByIdMap">
            <!-- 指定类中的属性 和 表中的字段 对应关系 -->
            <id property="stuNo"  column="id" />
            <result property="stuName" column="name" />
    </resultMap>
    
    b.resultType+HashMap

    select 表的字段名 "类的属性名" from... 来制定字段名 和属性名的对应关系

    <select id="queryStudentByIdWithHashMap"     parameterType="int"    resultType="student" >
        select id "stuNo",name "stuName" from student where id = #{id}
    </select>
    

    注意: 如果如果10个字段,但发现 某一个字段结果始终为默认值(0,0.0,null),则可能是 表的字段 和 类的属性名字写错。

    12.动态sql*

    两种动态sql方式 where 1=1 where标签方式

    <where>会自动处理第一个<if>标签中的 and,但不会处理之后<if>中的and

    <foreach>的使用

    <foreach>迭代的类型:数组、对象数组、集合、属性(Grade类: List<String> names)

    简单类型的数组:
    无论编写代码时,传递的是什么参数名(stuNos),在mapper.xml中 必须用array代替该数组

    集合:

    无论编写代码时,传递的是什么参数名(stuNos),在mapper.xml中 必须用list代替该数组 传递有关集合的代码 属性(Grade类: List<String> names): 传递属性有关代码

    对象数组:
    Student[] students = {student0,student1,student2} 每个studentx包含一个学号属性
    注意的几点:

        parameterType="Object[]" 
            <foreach collection="array" open=" and  stuno in (" close=")" 
                        item="student" separator=",">   
                        #{student.stuNo}
            </foreach>
    
    SQL片段:
    java:方法
    数据库:存储过程、存储函数
    Mybatis :SQL片段 
    

    a.提取相似代码

    b.引用 示例
    注:当要引用的sql语句在另一个xml文件中时,调用时refid属性中应该写namespace名.sql语句的id名

    13.关联查询

    一对一 image.png
    一对多 image.png
    注意与一对一语法上的区别,比如javaType与·ofType;association与collection

    14.日志:Log4j

    a.Log4j: log4j.jar (mybatis.zip中lib中包含此jar)
    b.开启日志,conf.xml

        <settings>
            <!-- 开启日志,并指定使用的具体日志 -->
            <setting name="logImpl" value="LOG4J"/>
        
        </settings>
    

    如果不指定,Mybatis就会根据以下顺序 寻找日志
    SLF4J →Apache Commons Logging →Log4j 2 → Log4j →JDK logging
    c.编写配置日志输出文件
    log4j.properties,内容

    log4j.rootLogger=DEBUG, stdout
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    

    日志级别:
    DEBUG<INFO<WARN<ERROR
    如果设置为info,则只显示 info及以上级别的信息;
    建议:在开发时设置debug,在运行时设置为info或以上。

    可以通过日志信息,相信的阅读mybatis执行情况( 观察mybatis实际执行sql语句 以及SQL中的参数 和返回结果)

    15.延迟加载(懒加载):

    一对一、一对多、多对一、多对多
    一对多:班级-学生 ,
    如果不采用延迟加载 (立即加载),查询时会将 一 和多 都查询,班级、班级中的所有学生。
    如果想要 暂时只查询1的一方, 而多的一方 先不查询 而是在需要的时候再去查询 -->延迟加载

    一对一:学生、学生证

    mybatis中使用延迟加载,需要先配置:

        <settings>
            <!-- 开启延迟加载 -->
            <setting name="lazyLoadingEnabled" value="true"/>
            
            <!-- 关闭立即加载 -->
            <setting name="aggressiveLazyLoading" value="false"/>
        </settings>
    

    如果增加了mapper.xml ,要修改conf.xml配置文件(将新增的mapper.xml加载进去)

    通过debug可以发现, 如果程序只需要学生,则只向数据库发送了查询学生的SQL;
    当我们后续 需要用到学生证的时候,再第二次发送 查询学生证的SQL。

    一对多:和一对一的延迟加载配置方法相同

    延迟加载的步骤:先查班级,按需查询学生
    1.开启延迟加载conf.xml配置settings
    2.配置mapper.xml
    写2个Mapper:
    班级mapper.xml

            <select id="queryClassAndStudents"   resultMap="class_student_lazyLoad_map">
            
                select  c.* from studentclass c
            </select>       
    
        <resultMap type="studentClass" id="class_student_lazyLoad_map">
                <!-- 因为 type的主类是班级,因此先配置班级的信息-->
                <id  property="classId" column="classId"/>
                <result  property="className" column="className"/>
                <!-- 配置成员属性学生,一对多;属性类型:javaType,属性的元素类型ofType -->
                <!-- 2222222再查班级对应的学生 -->
                <collection property="students" ofType="student" select="org.lanqiao.mapper.StudentMapper.queryStudentsByClassId" column="classid">
    
                </collection>
        </resultMap>
    

    即查询 学生的sql是通过 select属性指定,并且通过column指定外键
    学生mapper.xml

        <!-- 一对多,延迟加载需要的: 查询班级中的所有学生 -->
        <select id="queryStudentsByClassId" parameterType="int" resultType="student">
            select * from student where classId = #{classId}
        </select>
    
    image.png

    相关文章

      网友评论

          本文标题:MyBatis记错本

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