MyBatis&MyBatis-Plus

106 阅读2分钟

MyBatis & MyBatis plus

MyBatis

配置文件:放在类路径下

<?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>
<!--
     配置的顺序
    (properties?,settings?,typeAliases?,
    typeHandlers?,objectFactory?,objectWrapperFactory?,
    reflectorFactory?,plugins?,environments?,
    databaseIdProvider?,mappers?)
-->

<!--  引入properties文件, 使用${}访问  -->
    <properties resource="jdbc.properties"/>
<!---->

    <!--    类型别名-->
    <typeAliases>
<!--       为某个具体的类型设置别名
            在MyBatis的范围内就可以使用别名表示一个具体的类型
            type:设置需要起别名的类型
            alias:设置某个类型的别名
            不设置alias时, 别名默认是类名,且不区分大小写
-->
<!--        <typeAlias type="com.lang.mybatis.pojo.User" alias="User"/>-->
<!--        以包的方式设置别名
            此时这个包下的类,都全部拥有默认的别名
            即类名,且不区分大小写
-->
        <package name="com.lang.mybatis.pojo"/>
    </typeAliases>

<!--   配置连接数据库的环境
        属性default:设置默认使用的环境的id
-->
    <environments default="development">
<!--
        environment:设置一个具体的连接数据库的环境
        属性:
           1).设置环境的唯一标识, 不能重复
-->
        <environment id="development">
<!--            事务管理
                 属性
                   type:JDBC和MANAGED
                        JDBC:表示使用JDBC中的原生的事务管理方式
                        MANAGED:被管理,例如Spring
-->
            <transactionManager type="JDBC"/>
<!--            数据源
                属性
                   type:设置数据源的类型
                        1)POOLED:使用数据库连接池
                        2)UNPOOLED:不使用数据库连接池
                        3)JNDI:表示上下文中的数据源
-->
            <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>

<!--    引入mybatis的映射文件-->
    <mappers>
<!--        映射文件-->
<!--        <mapper resource="mappers/UserMapper.xml"/>-->


<!--        通过包引入mapper文件
            两个必须
            1).映射文件的包和mapper接口的包一样,
            2).映射文件的名字和mapper接口的名字一样,
-->
        <package name="com.lang.mybatis.mapper"/>
    </mappers>
</configuration>

读取mybatis-config.xml文件,获取SqlSession

public class SqlSessionUtil {
    public static SqlSession getSqlSession() {
        SqlSession sqlSession = null;
        try {
            //获取核心配置文件的输入流
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            //获取SqlSessionFactoryBuilder
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //获取SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
            //获取SqlSession
            //true可以自动提交
            sqlSession = sqlSessionFactory.openSession(true);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return sqlSession;
    }

获取参数时#{param}${param}有什么区别

  1. #{param}

    属于占位符,会自动添加引号

  2. ${param}

    是字符串形式,有SQL注入问题

exampleexample

<select id="getUserByUsername" resultType="User">
        select * from t_user where username=#{username};
        select * from t_user where username='${username}'
</select>

如果有两个及以上的参数,用@Param注解,或者直接可以用实体类接收

resultMap多对一对映关系

<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResult">
        select *
        from t_emp left join t_dept
        on t_emp.dept_id = t_dept.dept_id
        where t_emp.emp_id = #{empId}
    </select>
    <resultMap id="empAndDeptResult" type="Emp">
        <id column="emp_id" property="empId"/>
        <result column="emp_name" property="empName"/>
        <result column="emp_age" property="empAge"/>
        <result column="emp_gender" property="empGender"/>
        <!-- 处理实体类类型的属性,
			property 设置处理映射关系的属性名
			javaType 设置处理属性的类型
		-->
        <association property="dept" javaType="Dept">
            <id column="dept_id" property="deptId"/>
            <result column="dept_name" property="deptName"/>
        </association>
    </resultMap>

resultMap一对多对映关系

<!--    Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);
        处理一对多
-->
    <select id="getDeptAndEmpByDeptId" resultMap="getDeptAndEmpResultMap">
        select * from t_dept left join t_emp on t_dept.dept_id = t_emp.dept_id where t_dept.dept_id = #{deptId}
    </select>
    <resultMap id="getDeptAndEmpResultMap" type="Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
<!--        处理一对多的映射关系
            property 处理的属性名字
            ofType 集合中处理的属性的类型
-->
        <collection property="emps" ofType="Emp">
            <id column="emp_id" property="empId"/>
            <result column="emp_name" property="empName"/>
            <result column="emp_age" property="empAge"/>
            <result column="emp_gender" property="empGender"/>
        </collection>
    </resultMap>

MyBatis的一级缓存(default)

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问

使一级缓存失效的四种情况:

  1. 不同的SqlSession对应不同的一级缓存
  2. 同一个SqlSession但是查询条件不同
  3. 同一个SqlSession两次查询期间执行了任何一次增删改操作
  4. 同一个SqlSession两次查询期间手动清空了缓存(sqlSession.clearCache())

MyBatis的二级缓存(比一级缓存的范围大)

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取。

二级缓存开启的条件:

  1. 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
  2. 在映射文件中设置标签<cache/> 标签
  3. 二级缓存必须在SqlSession关闭或提交之后有效
  4. 查询的数据所转换的实体类类型必须实现序列化的接口

使二级缓存失效的情况:

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

MyBatis Plus

需要在启动类加@MapperScan(package = "mapper package"),或者在Mapper接口加上@Mapper

核心接口

Mapper

public interface UserMapper extends BaseMapper<User>{}

Service

public interface UserService extends IService<User>{}

ServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}

核心注解

@TableName类名和表名对映

@TableIdinsert的时候,MyBatis Plus用的是雪花算法

   /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
	/* type IdType.AUTO 是数据库自增
	        IdType.ASSIGN_ID 雪花算法
	*/
    private Long id;

也可以全局配置

#MyBatis-Plus相关配置
mybatis-plus:
  configuration:
    #配置日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      #配置mp的主键策略为自增
      id-type: auto

@TableFiled

  • @TableField(exist = false),表示此属性不是表的字段
  • @TableField(fill = FieldFill.INSERT)自动更新
  • @TableField("username")属性名和字段名不一致

@TableLogic逻辑删除

LambdaQueryWrapper

可以使用Lambda表达式

exampleexample

public void test(){
    String username = "a";
    Integer ageBegin = null;
    Integer ageEnd = 30;
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.like(StringUtils.isNotBlank(username), User::getName, username)
        .ge(ageBegin != null, User::getAge, ageBegin)
        .le(ageEnd != null, User::getAge, ageEnd);
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}

分页

@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

ExampleExample

LambdaQueryWrapper<VoucherOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(VoucherOrder::getId, 1);
        Page<VoucherOrder> page = new Page<>(1, 2);
        page(page, lambdaQueryWrapper);

本文由mdnice多平台发布