Mybatis完整笔记

Mybatis笔记

1、第一个Mybatis程序

  • 首先删除src,然后更改maven的路径设置。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5aJr7GP1-1602485368187)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20200908195726334.png)]

1、注意:配置pom.xml中的resources,防止资源导出失败的问题

<!--    配置resources,防止资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
  • 引入资源
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2、创建resources连接

1、mysql驱动问题
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
2、url问题
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>

?serverTimezone=UTC解决SQL时区问题

3、resources绑定mapper

mybatis-config.xml中mapper属性resources要填路径

3、乱码问题

  • 输出的xml文件中有乱码问题,删除输出文件中乱码,重新调试

4、mybatis-config.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核心配置文件-->
<configuration>
    <typeAliases>
        <package name="com.cat.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="com.cat.mapper.UserMapper"/>
    </mappers>
</configuration>

2、万能的Map

如果我们的实体类,或者数据库中的表,字段或者参数比较多,我们应当考虑使用Map!(虽然不规范,但是很实用,以后可能会帮到大忙)

1、Map

//    万能的Map
    int addUser(Map<String,Object>map);
    <insert id="addUser" parameterType="map">
-- 传递Map的键
        insert into mybatis.user(id,name,pwd) values(#{userid},#{userName},#{password});
    </insert>
//    万能的Map
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String,Object> map=new HashMap<String, Object>();
        map.put("userid",3);
        map.put("userName",4);
        map.put("password",5);
        
    }

2、模糊查询

  • Java代码执行的时候,传递通配符%李%
    //模糊查询
    List<User> getLikeUser(String value);
    <select id="getLikeUser" resultType="com.wildcata.pojo.User">
        select * from user where name like "%"#{value}"%"
    </select>
@Test
    public void getLikeUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> likeUser = mapper.getLikeUser("李");
        for (User user:likeUser){
            System.out.println(user);
        }
    }

3、配置解析

1、映射器

  • 接口和他的Mapper配置文件必须同名
  • 接口和他的Mapper配置文件必须放在同一文件夹下

2、生命周期和作用域

注意:错误的使用会导致非常严重的并发问题

1、SQLSessionFactory

  • 一旦创建就没有理由丢弃或重新创建另一个实例

3、免提交修改

public static SqlSession getSqlSession(){
    return sqlSessionFactory.openSession(true);
}

4、日志

在mybatis-config.xml中配置日志

SQL错误会有提示信息

1、标准日志

<settings>
<!--        标准的日志配置输出-->
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

2、LOG4J

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
  • log4j.properties配置
# 将等级为Debug的日志信息输出到console和file这两个目的地,console和file的定义如下
log4j.rootLogger=DEBUG, console,file
# 控制台输出的相关设置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold = DEBUG
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#%c: 输出日志信息所属的类目,通常就是所在类的全名  
#%m: 输出代码中指定的消息,产生的日志具体信息   
#%n: 输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行 
log4j.appender.console.layout.ConversionPattern=[%C]-%m%n 


# 文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = ./log/test.log
log4j.appender.file.MaxFileSize = 10mb
log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = [%p][%d{yy-MM-dd}][%c]%m%n

5、Lombok

@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
  • 常用的注解
@Data:无参构造函数,get,set,toString,...
@AllArgsConstructor
@NoArgsConstructor
  • 首先要在plugs中安装Lombok
  • 导入Lombok包
<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
</dependencies>

6、多对一(一对多)

  • 多个学生对一个老师
  • 对学生而言,多个学生关联一个老师
  • 对老师而言,是一种集合

1、测试环境

  • 导入lombok
  • 新建实体类Teacher,Student
  • 建立Mapper接口
  • 建立Mapper.xml文件
  • 在核心配置文件绑定所有的Mapper接口文件
  • 测试查询是否能成功

2、查询所有学生以及对应老师

使用resultMap

  • association 对象(老师是一个对象)
  • collection 集合(学生是一个集合)

1、方法一(子查询)

<select id="getAllStudent" resultMap="StudentTeacher">
    select * from student
</select>
<resultMap id="StudentTeacher" type="com.cat.pojo.Student">
    <association property="teacher" column="tid" javaType="com.cat.pojo.Teacher" select="getTeacherById"/>
</resultMap>
<select id="getTeacherById" resultType="com.cat.pojo.Teacher">
    select * from teacher where id=#{id}
</select>
@Test
public void getAllStudent(){
    SqlSession sqlSession = MybatisUilts.getSqlSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    List<Student> allStudent = mapper.getAllStudent();
    for(Student student:allStudent)
        System.out.println(student);
    sqlSession.close();
}

2、方法二(联表查询)

<select id="getAllStudent2" resultMap="StudentTeacher2">
    select s.id sid,s.name sname,t.name tname from student s,teacher t where s.tid=t.id
</select>
<resultMap id="StudentTeacher2" type="com.cat.pojo.Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" column="tid" javaType="com.cat.pojo.Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>
@Test
public void getAllStudent2(){
    SqlSession sqlSession = MybatisUilts.getSqlSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    List<Student> allStudent = mapper.getAllStudent2();
    for(Student student:allStudent)
        System.out.println(student);
    sqlSession.close();
}

7、一对多处理

一个老师多个学生

对老师而言是一对多关系

  • 环境搭建
<select id="getAllTeacher" resultMap="TeacherStudent">
    select t.id tid,t.name tname,s.id sid,s.name sname,s.tid tid from teacher t,student s where t.id=s.tid
</select>
<resultMap id="TeacherStudent" type="Teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <collection property="studentList" ofType="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
    </collection>
</resultMap>

<select id="getAllTeacher2" resultMap="TeacherStudent2">
    select * from teacher
</select>
<resultMap id="TeacherStudent2" type="Teacher">
    <collection property="studentList" column="id" javaType="ArrayList" ofType="Student" select="getStudent"/>
</resultMap>
<select id="getStudent" resultType="Student">
    select * from student where tid=#{tid}
</select>
@Test
public void getAllTeacher(){
    SqlSession sqlSession = MybatisUilts.getSqlSession();
    TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
    List<Teacher> allTeacher = mapper.getAllTeacher();
    for(Teacher teacher:allTeacher)
        System.out.println(teacher);
    sqlSession.close();
}
@Test
public void TeacherStudent2(){
    SqlSession sqlSession = MybatisUilts.getSqlSession();
    TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
    List<Teacher> allTeacher2 = mapper.getAllTeacher2();
    for (Teacher teacher : allTeacher2) {
        System.out.println(teacher);
    }
    sqlSession.close();

}

小结

  1. 关联-association【多对一】

  2. 集合-collection【一对多】

  3. javaType & ofType

    • javaType 用来指定实体类中属性的类型
    • ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束

注意点:

  • 保证SQL的通俗易懂(可读性)
  • 注意一对多和多对一中的,属性名和字段问题
  • 有问题不好排错,可以使用日志
  • 慢SQL 1s 1000s(尽量避免慢SQL)

面试高频

  • mysql引擎
  • innodb底层原理
  • 索引
  • 索引优化

8、动态SQL

IF

<select id="getBlogByTItleOrAuther" parameterType="map" resultType="Blog">
    select * from blog
    <where>
        <if test="title !=null">
            and title=#{title}
        </if>
        <if test="author !=null">
            and author=#{author}
        </if>
    </where>
</select>
  • where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
  • set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号
  • where,有前缀and | or
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>
  • prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。
  • set有后缀,
<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

总结

所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码

SQL片段

有时,我们需要将一些功能部分抽取出来,方便复用

1、使用SQL标签抽取公共部分

<sql id="if-title-author">
    <if test="title !=null">
        and title=#{title}
    </if>
    <if test="author !=null">
        and author=#{author}
    </if>
</sql>

2、在需要使用的地方使用include标签引用

<select id="getBlogByTItleOrAuther" parameterType="map" resultType="Blog">
    select * from blog
    <where>
        <include refid="if-title-author"></include>
    </where>
</select>

注意事项:

  • 最好基于单表来定义SQL片段
  • 不要存在where标签

Foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符

<select id="queryForeach" parameterType="map" resultType="Blog">
    select * from blog
    <where>
        <foreach collection="ids" item="id" open="(" close=")" separator="or">
            id = #{id}
        </foreach>
    </where>
</select>

动态SQL就是拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以
建议:

  • 先在mysql中写出完整的SQL,再去对应的去修改成我们的动态SQL实现通用即可

9、缓存

减少和数据库的交互次数

经常查询并且不常改变的数据

  • 一级缓存二级缓存
    • 默认只有一级缓存开启(SQLSession,本地)
    • 二级缓存需要手动开启和配置,基于namespace级别的缓存
    • 为了提高拓展性,mybatis定义了缓存接口cache,我们可以通过他来自定义二级缓存
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值