MyBatis记错本

2019-02-18  本文已影响0人  值得_e36c

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
上一篇下一篇

猜你喜欢

热点阅读