mybatis入门

Mybatis

入门

导入相关包,mybatis,mysql-connector-java

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">
<!-- mybatis的主配置文件 -->
<configuration>
    <!-- 配置环境 -->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
    <mappers>
      	xml方式
        <mapper resource="com/yyx/dao/IUserDao.xml"/>
      	注解
        <mapper class="全限定类名"/>
    </mappers>
</configuration>

xml方式的指定的IUserDao.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">
<mapper namespace="com.yyx.dao.UserDao">
    <!--配置查询所有-->
    <select id="findAll" resultType="com.yyx.domain.User">
        select * from user
    </select>
</mapper>

入门测试类:

InputStream in = null;
try {
    in = Resources.getResourceAsStream("SqlMapConfig.xml");
} catch (IOException e) {						加载文件的两种方式1.类加载器加载
                                                   2.serveletContext获得路径
    e.printStackTrace();
}
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();构建者模式
SqlSessionFactory factory = builder.build(in);工厂模式
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
UserDao userDao = session.getMapper(UserDao.class);代理模式
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users){
    System.out.println(user);
}
//6.释放资源
session.close();
try {
    in.close();
} catch (IOException e) {
    e.printStackTrace();
}

如果是注解的方式 将注解@Select("select * from user")放在接口方法上

Mybatis在使用代理对象实现增删改查时做了两件事创建代理对象,在代理对象中调用selectList

增删改,并且增删改一定要提交事务

插入:<insert id="方法名" parameterType="参数,如果是pojo类要写全限定类名">
    sql语句   #{获得参数}
</insert>
更新:<update id="" parameterType="" >
        
    </update>
删除:    <delete id="" parameterType="">
        
    </delete>
配置解析
环境配置(environments)

MyBatis 可以配置成适应多种环境,尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

属性(properties)

引用配置文件,这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。

<properties resource="">
    <property name="" value=""/>但优先使用外部配置文件
</properties>
类型别名(typeAliases)

类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。

注解方式@Alias("名字")

映射器(mappers)

mapper的注册,可以通过resource,可以通过class或者通过package

字段名与实体类属性名不同

将resultType改为resultMap取一个名字,再配置一个

?
?
?

使用注解开发

1.注解在接口上实现

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

2.需要在核心配置中绑定接口

<mappers>
    <mapper class="com.yyx.dao.UserDao"/>
</mappers>

本质:反射机制实现。 底层:动态代理

@insert 插入。@update 更新。 @delete删除。 在写参数的时候加上@param 取一个正确的名字以便sql中参数的使用,引用类型不需要加

多对一

第一种方式查询。 多个学生对应一个老师

<select id="findAll" resultMap="ST" >
    select * from user
</select>
<resultMap id="ST" type="User">
    <result 字段名:property=""数据库中的名字: column="" />
    //关联,对象
    <association property="对象" column="字段名比如老师的id " javaType="teacher" select="getTeacher"  嵌套查询/>
</resultMap>
<select id="getTeacher" resultMap="teacher">
    select * from teacher where id=#{id}相当于从上面的association取到老师的id然后查出老师对象赋值
</select>

第二种方式根据结果

<select id="findAll" resultMap="ST">
    select s.id sid,s.name sname,t.name tname from user s, teacher t where s.tid = t.id
</select>
<resultMap id="ST" type="User">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

一对多

一个老师对应多个学生 对象用association,集合用collection

按结果嵌套查询

<select id="getTeacher" resultMap="TeacherStudent">
    select s.id sid,s.name sname,t.id tid,t.name tnam from teacher t,student s where s.tid = t.id and t.id=#{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <collection property="students" ofType="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
    </collection>
</resultMap>

第二种方式

<select id="getTeacher" resultMap="TeacherStudent">
    select * from teacher where id = #{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
    <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
    select * from student where tid=#{tid}
</select>

动态sql

if
<select id="queryBlog" parameterType="map" resultType="Blog">
    select * from blog where 1=1
    <if test="author != null">
        and author = #{author}
    </if>
</select>
choose<when,otherwise>

和java中的switch很像

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>
Trim<where,set>

像上面的where 1=1 是不会去写的,但不能出现where and这个时候我们会省略where 使用这个标签

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>
<select id="queryBlog" parameterType="map" resultType="Blog">
    select * from blog 
    <where>
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
    </where>
</select>
<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留)

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>
foreach

动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

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

注意 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

SQL片段

使用sql标签抽取公共部分

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

2.在需要使用的地方使用include

<select id="queryBlog" parameterType="map" resultType="Blog">
    select * from blog
    <where>
        <include refid="s"></include>
    </where>
</select>

最好基于单表来定义sql片段,不要存在where标签,where有优化条件

缓存

SqlSession默认开启一级缓存,仅仅对一个会话中的数据进行缓存

sql映射文件中添加开启二级缓存,可以先在xml中setting中开启全局缓存,cacheEnable

在查询的时候会将数据保存在二级缓存,当一级缓存没有的时候,会从二级缓存里面找

spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

mybatis.type-aliases-package=com.springboot.springbootmybatis.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
springboot 中整理mybatis的配置