Mybatis基础总结

mybatis基础项目依赖

mybatis、mysql驱动、junit、防止资源导入失败

扩展:log4j、lombok、分页插件

XML 复制代码
<!-- Mybatis依赖-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <!-- Mysql连接依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.21</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.1</version>
        <scope>test</scope>
    </dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
    <scope>provided</scope>
</dependency>
        <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.2.0</version>
        </dependency>

资源导出问题解决

XML 复制代码
<!--在build中配置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>

log4j.properties文件设置

XML 复制代码
#将等级为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
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/serenity.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

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

lombok常用:@Data、@AllArgsConstructor、@NoArgsConstructor

mybatis-config.xml配置文件

包括日志、驼峰命名、别名、环境连接、绑定Mapper配置文件,二级缓存、分页插件等基础配置。

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>
    <!-- Load external configuration files-->
    <properties resource="db.properties"/>
    <settings>
        <!--Set up a default logging factory-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
<!--Set up camelCase naming mapping-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
<!--Enable global configuration caching-->
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <typeAliases>
        <!--<typeAlias type="com.User" alias="User"/>-->
        <package name="com.serenity.pojo"/>
    </typeAliases>
<!--setting limit page-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>
    <!--binding on interface-->
    <mappers>
        <mapper class="com.serenity.dao.TeacherMapper"/>
        <mapper class="com.serenity.dao.StudentMapper"/>
    </mappers>
</configuration>

db.propertise数据库文件

XML 复制代码
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatistest?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username=root
password=123456

Mapper映射文件的头文件

通过resultMap实现数据库列名和属性值一一对应(使用列和属性都写)。

  • resultMap中的id:唯一标识,不能重复
  • type:映射的类型。
    • id标签:设置主键的映射关系
    • result:设置普通字段的映射关系
      • property:设置的是映射关系中的属性名,必须是type属性所设置的实体类类型中的属性。
      • column:设置映射关系中的字段名,必须是sql语句中查询出的字段名

注意namespace命名空间的接口映射,接口中的方法名需要与select中的id名一致。其中cache时是开启二级缓存

XML 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.serenity.mybatis.mapper.EmpMapper">
<cache/>
    <resultMap id="empResultMap" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
    </resultMap>
    <select id="getAllEmp" resultMap="empResultMap">
        select * from emp;
    </select>
</mapper>

采用注解开发

java 复制代码
//通过id查询用户,方法中存在多个参数时,所有参数前面必须加上@Param
    @Select("select * from user where id=#{id}")
    User getUserById(@Param("id") int id);
//增加用户
    @Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")
    int addUser(User user);
//修改用户
    @Update("update user set name=#{name},pwd=#{password} where id=#{id}")
    int updateUser(User user);
//删除用户
    @Delete("delete from user where id=#{uid}")
    int deleteUser(@Param("uid") int id);

Mybatis工具包

java 复制代码
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        String resource="mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

一对多和多对一的处理

java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp {
    private int eid;
    private String empName;
    private Integer age;
    private String sex;
    private String email;
    //多对一,创建这个一的对象
    private Dept dept;
}
java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
    private Integer did;
    private String deptName;
    //一对多,创建这个对多的集合
    List<Emp> emps;
}

以下是两张表的信息:

emp表

t_dept表

多对一映射处理

级联resulrMap

使用resultMap完成结果集映射,property中的dept是实体类Emp中设置的。

XML 复制代码
<resultMap id="empAndDeptResultMapone" type="Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <!--dept.did is on the POJO about property ,column is binding did of dept-->
        <result property="dept.did" column="did"></result>
        <result property="dept.deptName" column="dept_name"></result>
    </resultMap>
    <!--selec emp information and some depy infoormotion-->
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapone">
        select * from emp left join t_dept on emp.did=t_dept.did where emp.eid=#{eid}
    </select>

进行多表查询测试:

java 复制代码
 @Test
    public void testGetEmpAndDept(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDept(1);
        System.out.println(emp);
    }

association

其他地方与法一一样,只需要更改字段不一致部分。association专门处理多对一的映射关系。

property中的dept是对应emp中的属性名,

javaType中的Dept对应的是属性名的类型。

XML 复制代码
<association property="dept" javaType="Dept">
            <id property="did" column="did"></id>
            <result property="deptName" column="dept_name"></result>
        </association>

分布查询association+select

根据id查询员工信息

根据id查询部门信息

查询结果为:

java 复制代码
@Test
    public void testGetEmpAndDeptByStep(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAnddeptBystepOne(3);
        System.out.println(emp);
    }

一对多映射处理

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
    private Integer did;
    private String deptName;
    //一对多,创建这个对多的集合
    List<Emp> emps;
}

collection

ofType:表示集合存放的什么类型

测试:

分部查询collection+select

查询员工信息:

测试结果:

分布查询优点:延迟加载

想要实现延迟加载,必须在核心配置文件中设置全局配置信息。

lazyLoadingEnable:延迟加载的全局开关 ,开启时,所有关联对象都会延迟加载。设置为true

aggressiveLazyLoading :开启时,任何方法的调用都会加载该对象的所有属性,否则,每个属性会按需加载。设置为false

此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql,此时可通过association和collection中的fetchType属性设置当前的分布查询是否所有延迟加载,fetchType="lazy(延迟加载)|eager(立即加载)"

XML 复制代码
<!--Enable delayed loading-->
        <setting name="lazyLoadingEnabled" value="true"/>

多条件查询

IF

if标签中的test为判断语句 是否为空来决定标签中的内容是否需要拼接到SQL语句 ,paramaterType可以指定SQL语句的参数类型,可以是基本数据类(int、string等),也可以是复杂数据类型(类和Map)

where

**where元素只会在至少有一个子元素的条件返回SQL子句的情况下才去插入"where"子句,而且,若语句的开头为"and"或"or",where元素也会将它们去除。**下面例子,如果第一个条件不成立,where自动去掉and。

但是where标签中没有内容时,此时where标签没有任何效果,不会自动生成where。

XML 复制代码
<select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <if test="title!=null">
            title=#{title}
        </if>
            <if test="author!=null">
                and author=#{author}
            </if>
        </where>
    </select>

set

wher无法将判断语句后面的and或or去掉,set元素会动态前置set关键字,同时也会删掉无关的逗号或and,or

XML 复制代码
 <update id="updateBlog" parameterType="map">
        update blog
        <set>
            <if test="title!=null">
                title=#{title},
            </if>
            <if test="author!=null">
                author=#{author}
            </if>
        </set>
            where id=#{id}
    </update>

trim(定制标签)

trim作用位置与之前的where一致,添加前缀值where,删掉前缀文本and或or。

XML 复制代码
<trim prefix="where" prefixOverrides="and|or">
    ...
</trim>

添加前缀值set,删掉后缀文本,

XML 复制代码
<trim prefix="set" suffixOverrides=",">
    ...
</trim>

choose、when、otherwise

有时我们不想应用到所有的条件语句,只想要其中一项,choose能够满足我们的需求,它有点像Java中的switch语句。它能够按照提供了title就根据title查找,提供了author就按照author查找,若两者都没有提供,就返回所有符号条件的Blog

  • 当所有when中的条件都满足时,优先满足第一条。
  • 当when的条件都不满足时,执行otherwise
  • when至少有一个,otherwise最多只有一个
XML 复制代码
<select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <choose>
                <when test="title!=null">
                    title=#{title}
                </when>
                <when test="author!=null">
                    and author=#{author}
                </when>
                <otherwise>
                    and view=#{view}
                </otherwise>
            </choose>
        </where>
    </select>

foreach

map中存在一个集合,从集合中遍历id。

  • collection:标识要遍历的数组或集合名
  • item:标识数组中的每一个元素
  • open:前缀
  • close:后缀
  • separator:每一个循环体的分隔符
XML 复制代码
<select id="queryBlogForeach" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <foreach collection="ids" item="id" open="(" close=")" separator="or">
            id=#{id}
            </foreach>
        </where>
    </select>

SQL片段(不常用)

抽取SQL语句的公共部分

XML 复制代码
<sql id="select_queryBlogIF_if">
            <if test="title!=null">
                title=#{title}
            </if>
            <if test="author!=null">
                and author=#{author}
            </if>
    </sql>

需要使用的地方使用include标签引用即可

XML 复制代码
<select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="select_queryBlogIF_if"></include>
        </where>
    </select>