Mybatis

Mybatis

是一款优秀的持久层框架,它支持定制化 SQL
避免了几乎所有的 JDBC 代码和手动设置参数

导入jar

<!--mybatis依赖包-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>
<!--jdbc依赖包-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--lombok的包-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

数据映射

pojo: 程序通过对象封装数据信息

一个pojo对象要求映射一张数据表
对象名称 映射数据表表名
对象的属性 映射数据表中的字段

也就是说 数据库里面的一个表对应Java里面的一个对象
类似于如下

@Data // 添加 get set方法
@Accessors(chain = true) // 重写set方法
@NoArgsConstructor// 无参构造
@AllArgsConstructor// 全参构造
// 实现 序列化接口
public class User implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}

resources目录里创建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>

    <!--环境配置标签-->
    <environments default="development">
        
        <!--编辑开发环境-->
        <environment id="development">
<!--            mybatis中采用 jdbc的事务控制-->
            <transactionManager type="JDBC"/>
<!--            jdbc连接 池-->
            <dataSource type="POOLED">
                <!--使用高版本的驱动-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--数据库的地址-->
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&amp;useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;allowMultiQueries=true"/>
                <!-- 用户名 和密码 -->
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--Mybatis加载Mapper映射文件-->
    <!--添加对应的映射文件路径-->
    <mappers>
        <!--这里的路径一定要匹配上 -->
        <mapper resource="mappers/userMapper.xml"/>
    </mappers>
</configuration>

编辑映射文件

将对象和数据库里的表对应起来
配置xml映射文件
一个接口对应一个映射文件
如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace是mybaits映射文件的唯一标识,与接口对应-->
<!--写的是 包路径-->
<mapper namespace="com.jt.mapper.UserMapper">
    <!-- 和 接口里的方法名 对应 -->
    <!--  执行 插入数据操作 使用insert标签 <insert id=""></insert>-->
    <!--  执行 修改操作 <update id=""></update>-->
    <!--id 表示接口方法 
        resultType 返回值结果类型 对象
    -->
    <select id="findAll" resultType="com.jt.pojo.User">
        select * from demo_user
    </select>
</mapper>

使用

public void testDemo1() throws IOException {
    // 指定配置文件的根目录
    String resource = "mybatis-config.xml";

    // 通过IO流 加载配置文件
    // 通过流文件 读取里面创建了几个 映射
    InputStream inputStream = Resources.getResourceAsStream(resource);

    // builder 建造者模式
    // 实例化 工厂对象
    //  SqlSessionFactory  目的是获取 SqlSession
    // SqlSession  包装了 数据库的连接 和 连接器对象
    // 通过SqlSession 可以直接连接数据库
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
    // 打开数据库连接
    SqlSession sqlSession = sqlSessionFactory.openSession();
    
    // 获取接口对象
    UserMapper userMapper = sqlSession.getMapper(userMapper.class);
    
    // 完成业务调用
    List<user> userList = userMapper.findAll();

    System.out.println(userList);

    //关闭连接
    sqlSession.close();

}

方法2

由于Mybatis依赖了JDBC的包 但是该包文件是启动项,
当主启动项开始加载启动项
但是JDBC需要连接数据库所以必须有配置相关的信息

配置resources文件夹里的application.yml文件

# 配置端口
server:
  port: 8090
#  配置数据源
# driver-class-name 包文件 cj.jdbc 是高版本的
# url  数据库的地址
# username 数据库的用户名
# password  数据库的密码 密码开头是0的需要使用引号包裹 如 "01234"
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root

#  type-aliases-package pojo包路径
mybatis:
  type-aliases-package: com.jt.pojo
#  mapper-locations  xml的配置文件存放路径
  mapper-locations: classpath:/mappers/*.xml
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true

01
Mapper层增加注解

@Mapper // 将接口交给 spring 管理容器进行管理 存储的是Map<UserMapper,JDK代理对象>
public interface UserMapper {
    // 查询 demo_user的全部数据
    List<User> findAll();
}

使用

@Test
public void testDemo(){

    List<User> userList = userMapper.findAll();

    System.out.println(userList);
}

MyBatis的增删改查

xml文件里的配置

<!-- 根据id查询用户  
findUserById 是方法名
resultType  是返回值 此写法是返回User对象
-->
<select id="findUserById" resultType="com.jt.pojo.User">
    select * from  demo_user where id=#{id}
</select>

使用

@Mapper // 将接口交给 spring 管理容器进行管理 存储的是Map<UserMapper,JDK代理对象>
public interface UserMapper {
    // 根据id查询数据库
    User findUserById(int id);
}
@Autowired
private UserMapper userMapper;
@Test
public void testFindUserById(){
    User user = userMapper.findUserById(1);

    System.out.println(user);
}

打印 sql日志

# 打印 sql
#  打印com.jt.mapper 的sql日志
logging:
  level:
   com.jt.mapper: debug

如果多个参数需要进行传递一般采用对象的方式封装
如:

User user = new User();
user.setName("白龙驴");
user.setAge(200);

List<User> userList = userMapper.findUserByNA(user);

多个数据查询

<!-- 参数传递的规则
     如果是 单个 参数则使用 #{key}
     如果是 对象 参数则使用 #{属性}
 -->
<select id="findUserByNA" resultType="User">
    select * from demo_user where name=#{name} and age=#{age}
</select>

如果多个参数不方便封装
使用万能集合Map

int minAge = 18;
int maxAge = 200;
HashMap<String, Integer> map = new HashMap<>();

map.put("minAge", minAge);
map.put("maxAge", maxAge);

List<User> userList = userMapper.findUserByAge(map);

或者可以使用多个值
但是在Mapper里面使用注解@Param
如:

@Mapper // 将接口交给 spring 管理容器进行管理
public interface UserMapper {
// 原则上 支持单值 传参  多值封装成 单值
// 原理是将多个值自动封装成 Map 集合
List<User> findUserByAge2(@Param("minAge") int minAge,@Param("maxAge") int maxAge);
}

查询范围的值

<!--特殊转义字符
    >   &gt;
    <   &lt;
    &   &amp;
    万能转义标签   <![CDATA[ 需要转义的内容 ]]>
	万能转义 需要把 sql 语句 整体写入里面 如:
	<![CDATA[ select * from demo_user where age > #{minAge} and age < #{maxAge} ]]>
    -->
<select id="findUserByAge" resultType="User">
    select * from demo_user where age > #{minAge} and age &lt; #{maxAge}
</select>

模糊查询

<select id="findUserByLike" resultType="User">
    <![CDATA[
            select * from demo_user where name like #{name}
    ]]>
</select>
String name = "%" + "李" + "%";

List<User> userList = userMapper.findUserByLike(name);

System.out.println(userList);
sql标签

sql语句中经常出现重复的数据如果每次
重复的内容都手写则开发效率低

使用sql标签进行抽取

<!-- sql标签 抽取公共的sql语句 -->
<sql id="tableColumn">
    select * from demo_user
</sql>

使用sql标签

<select id="findUserByNA" resultType="User">
    <include refid="tableColumn"/> 
    where name=#{name} and age=#{age}
</select>

mybatis的循环

foreach 遍历标签
collection 需要遍历的集合

  1. 数组 关键字 array

  2. list集合 关键字 list

  3. ap<key,arr/list> 关键字 key

    open/close 循环的开始结束符

    item 当前遍历数据的 变量
    separator 表示分隔符

<select id="findById" resultType="User">
    select * from demo_user where id in 
    <foreach collection="array" open="(" close=")" item="id" separator=",">
		#{id}
    </foreach>
</select>

新增删除操作基本相同

新增

<insert id="saveUser">
    insert into demo_user(name,age,sex)
    			values(#{name},#{age},#{sex})
</insert>

新增操作默认是有返回值 int 类型
可以不接收

动态sql

根据传过来的对象中的属性不为空(null) 当做属性

<!-- where标签用来去除 多余的一个 and/or -->
<!-- if 判断属性如果不为空则查询 -->
<select id="findUserList" resultType="User">
    select * from demo_user
    <where>
        <if test="id !=null">id = #{id}</if>
        <if test="name !=null">and name = #{name}</if>
        <if test="age !=null">and age = #{age}</if>
        <if test="sex !=null">and sex = #{sex}</if>
    </where>
</select>

动态的更新

<!--去除if 里面最后一个逗号-->
<update id="updateUser">
    update demo_user
    <set> 
        <if test="name !=null">name = #{name},</if>
        <if test="age !=null">age = #{age},</if>
        <if test="sex !=null">sex = #{sex}</if>
    </set>
    where id = #{id}
</update>

sql分支语句
如果不满足某个条件
则使用另一个条件

<!-- 相当于 swatch catch  
            choose 是开启判断
            when  是否满足 test 里的判断
                如果是 查询里面的语句 不满足 跳过 往下执行 
                是否有下一个 when 如果上方的条件都没有满足执行 otherwise 相当于 default
-->
<select id="findUserByNS" resultType="User">
    select * from demo_user
    <where>
        <choose>
            <when test="name !=null">
                name = #{name}
            </when>
            <otherwise>
                sex = #{sex}
            </otherwise>
        </choose>
    </where>
</select>

表字段与对象属性不一致

关于映射文件的返回值resultType 只能支持
数据库的表 字段名称属性名称 一致才能自动映射

<select id="findAll" resultType="Dog">
    select * from dog
</select>

不满足时
使用resultMap

<select id="findAll" resultMap="dogRM">
    select * from dog
</select>
<!--自己封装 映射关系-->
<resultMap id="dogRM" type="Dog">
    <!-- ID代表主键
                -->
    <id column="dog_id" property="dogId"></id>
    <!-- 结果集 -->
    <result column="dog_name" property="dogName"></result>
    <!-- 属性名 与表名一致时 可以不用封装 -->
</resultMap>

配置文件中的驼峰映射

如果经常出现
数据库表字段user_id
Java属性userId
两者是驼峰映射关系

可以在application.yml文件里配置如下
开启了驼峰映射规则

mybatis:
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true

关联关系

表与表之间的关联如
一个老师对应多个学生
一个学生对应多个老师

封装pojo文件时对应关联关系
如: 一个员工对应一个部门

public class Emp implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    //一个员工对应一个部门
    private Dept dept;
}

xml文件写法
resultMap标签使用assoction标签

<!--
    如果操作的是 单标 使用resultType
    如果进行的是 关联 使用resultMap
    如果是多表进行关联 结果集不允许出现重名字段
-->
<select id="findAll" resultMap="empMap">
    SELECT e.id,e.name,e.age,e.dept_id,d.dept_name FROM emp e LEFT JOIN dept d ON e.dept_id=d.dept_id;
</select>

<!-- 没有关联映射时 对象里的属性 和 数据库表里的字段 同名可以不写   -->
<!-- 如果有关联映射时 添加自动映射的开关 autoMapping   -->
<!-- autoMapping 只对添加的当前对象有效 如果有多个对象 添加多次   -->
<resultMap id="empMap" type="Emp" autoMapping="true">
    <!--主键 必须写-->
    <id column="id" property="id"/>

    <!--
        一对一关联封装 使用 association
		property 指对象里的属性 dept属性
        必须指定属性的类型  javaType 属性 封装的对象
     -->
    <!-- 添加自动映射的开关 autoMapping="true" -->
    <association property="dept" javaType="Dept" autoMapping="true">
        <!-- Dept的主键 -->
        <id column="dept_id" property="deptId"/>
    </association>
</resultMap>

一对多关联
如: 一个部门对应多个员工

public class Dept implements Serializable {
    private Integer deptId;
    private String deptName;
    // 一个部门对应多个员工
    private List<Emp> emps;//使用集合封装
}

xml 文件配置
resulMap标签里使用collection标签

<resultMap id="deptRM" type="Dept" autoMapping="true">
    <id property="deptId" column="dept_id"/>
    
    <!-- 一对多封装 collection -->
    <!--
        property 对象里的属性
        ofType   封装的对应对象
    -->
    <collection property="emps" ofType="Emp" autoMapping="true">
        <id property="id" column="id"/>
    </collection>
</resultMap>

注解sql

利用注解自动映射
注解和映射文件 二选一

@Mapper
public interface UserAnnoMapper {

    @Select("select * from demo_user")
    List<User> findAll();
}

使用参数

@Mapper
public interface UserAnnoMapper {

    @Select("select * from demo_user")
    List<User> findAll();

    @Select("select * from demo_user where id=#{id}")
    User findUserById(int id);
}

查询注解@Select
插入注解@Insert
更新注解@Update
删除注解@Delete

MyBatis缓存

MyBatis中提供了两种缓存机制
一级缓存: 在同一个sqlSession内实现数据共享
一个人多次查询同一个sql 默认开启
二级缓存: 在同一个sqlSessionFactory生产的sqlSession数据共享
并发操作 默认开启

一级缓存@Transactional

如果采用 springboot 的方式测试 一级缓存无效
因为 springboot 整合mybatis 使用查询时 springBoot会开启多个 sqlSession
创建了多个 sqlSession 对象
需要添加@Transactional

@Test
@Transactional // 控制事务
public void testCache1(){

    List<User> userList = userAnnoMapper.findCache1();
    List<User> userList1 = userAnnoMapper.findCache1();
    List<User> userList2 = userAnnoMapper.findCache1();
    List<User> userList3 = userAnnoMapper.findCache1();
    List<User> userList4 = userAnnoMapper.findCache1();
}

开启二级缓存

二级缓存springboot 默认开启
但是需要一些配置xml文件里面增加一个标签

<mapper namespace="com.jt.mapper.UserAnnoMapper">
    <!--
        开启二级缓存
        pojo 里面的对象必须实现 序列化 Serializable
    -->
    <cache/>
    <select id="findCache1" resultType="User">
           select * from demo_user
    </select>
</mapper>

pojo里的对象必须实现 序列化serializable

// 序列化接口 Serializable
public class User implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}

注解开启二级缓存

在mapper里使用注解@CacheNamespace

@Mapper
@CacheNamespace
public interface UserAnnoMapper {
    @Select("select * from demo_user")
    List<User> findAll();
}

如果使用注解则
xml文件里面不能使用<cache/> 标签

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值