SQL极简教程 · MySQL · MyBatis · JPA 技术笔记 教程 总结MyBatis+SpringMVC+SpringBoot

Java基础框架之Mybatis

2020-04-12  本文已影响0人  在error边缘疯狂试探

什么是Mybatis?

导入依赖

<!--Mybatis 依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>

使用XML的方式配置Mybatis

<!--这是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">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=true&amp;useUnicode=true&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
<!--    <mappers>-->
<!--        <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
<!--    </mappers>-->
</configuration>

获得sqlSession对象

public class MybatsiUtils  {

    private static SqlSessionFactory sqlSessionFactory;
    static {

        try {
            //使用Mybatis第一步,获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";//这是配置Mybatis的文件名
            InputStream inputStream = Resources.getResourceAsStream(resource);//通过流的形式获得xml文件的信息,传给获取sqlSessionFactory工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //既然有了获取sqlSessionFactory,顾名思义,我们就可以从中获得sqlsession的实例了
    public static SqlSession getSqlSession(){
        //sqlSession 完全包含了面向数据库执行SQL命令所需的所有方法,这就有点像connection
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return  sqlSession;
    }
}

开始第一个Mybatis程序

<?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:绑定对应的IUserMapper接口-->
<mapper namespace="com.cwx.dao.IUserMapper">
<!--select 查询语句,id:IUserMapper接口文件的方法名,resultType:返回结果的类型,必须写全路径,parameterType:参数的类型,若没带参数就不用写-->
  <select id="getUserList" resultType="com.cwx.entity.User">
    select * from test
  </select>
  <select id="getUserListByID" parameterType="int" resultType="com.cwx.entity.User">
    select * from test where id = #{id}<!--这里用的id是mapper接口中的参数名,要一致-->
  </select>
    <!--插入一个数据,参数名用实体类定义的私有变量名,没有返回值-->
    <insert id="addUser" parameterType="com.cwx.entity.User">
        insert into test (name,age,pwd) values (#{name},#{age},#{pwd})
  </insert>
    <!--更新一个数据,没有返回值-->
  <update id="updateUser" parameterType="com.cwx.entity.User">
    update test set age=#{age},pwd=#{pwd} where name=#{name}
</update>
</mapper>
 <mappers>
       <mapper resource="mapper/UserMapper.xml"/>
  </mappers>
@Test
 public void mybatisTest(){
        //第一步,获得sqlsession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession;
        //第二步,利用sqlSession实现执行语句
        UserMapper userMapper = sqlSession.getMapper(IUserMapper.class);//获得dao层的Mapper接口,放入工厂中
        List<User> userList = userMapper.getUserList();//执行配置文件里的方法,若方法里有参数就在这写入
        for(User user : userList){
        System.out.println(user);
        sqlSession.close();//必须要关闭,sqlSession线程是不安全的
  }
  }

Tips:使用增删改操作需要添加事务,即测试时最后要提交事务sqlSession.commit()

Mybatis使用Map

当方法的参数有多个时使用map或者当我们实体类或数据库中的字段或参数比较多时,当我们进行修改时,只修改某个参数就可以使用map,使用map可以只用写我们需要修改的值,其他的不用动或者。

 <update id="updateUser2" parameterType="map"><!--参数类型为map-->
    update test pwd=#{pwd} where name=#{name}<!--这里只用修改pwd-->
</update>

测试类:

@Test
public void testUpdate(){
     //第一步,获得sqlsession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession;
        //第二步,利用sqlSession实现执行语句
        UserMapper userMapper = sqlSession.getMapper(IUserMapper.class);//获得dao层的Mapper接口,放入工厂中
        Map<String,Object> map = new HashMap<String,Object>();
            map.put("name","cwx");
            map.put("pwd",123456);
        userMapper.updateUser2(map)
        sqlSession.commit();
        sqlSession.close();
}

环境配置(environments)

Tips:mybatis默认事务是JDBC(还有一个是MANAGED),默认数据源是POOLED,Mybatis可以配置多个环境,但每个Sqlsession实例只能选择一种环境。

属性(properties)

我们可以通过properties属性来引用配置文件,例如:

<properties resource="db.properties">
  <property name ="username" value="root" />
  <property name ="password" value="111111" />
</properties>

【注意点】: 若db.properties文件中和这里的property属性有一样的字段,优先使用db.properties里的,其它地方通过#{}符号引用属性值。

Tips:${}#{}区别:两者都可以获得参数,但是#{}能够更大程度的防止SQL注入问题,而${}无法防止SQL注入。

类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

<typeAliases>
  <typeAlias alias="User" type="com.cwx.entity.User"/>
</typeAliases>
<!--或者使用包名,当实体类有很多时用这种-->
<!--MyBatis 会在包名下面搜索需要的 Java Bean,别名是开头字母小写,如:user-->
<typeAliases>
  <package name="com.cwx.entity"/>
</typeAliases>

Tips:MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用,此时Mybatis-plus应运而生,更加简化了操作。

映射器(mappers)

在MapperRegister中注册mapper,一般就使用<mapper resource="mapper/UserMapper.xml"/>方式,其他方式和注意点到 Mybatis-3官方文档里看映射器的方式 里面查看。

生命周期和作用域(Scope)

ResultMap结果集映射

<!--实现结果集映射,保证实体类中的名和数据库字段名对应-->
<resultMap id="UserMap" type="com.cwx.entity.User">
<!--  column:是数据库中的字段,property:实体类中的属性名-->
  <result column="id" property="id" />  <!--名字相同可以不用写-->
  <result column="name" property="name" />  <!--名字相同可以不用写-->
  <result column="pwd" property="password" />  <!--这里的名字不一样,这都是简单版的结果映射-->
</resultMap>

<select id="getUserById" resultMap="UserMap">
      select * from test where id=#{id}
</select>

分页

<select id="getUserLimit" paramType="map" resutlMap="userMap">
    select * from test limit #{startIndex},#{pageSize}
</select>

使用注解开发

@Select(select * form test)
List<User> getUserList();//如果方法中有多个参数,就使用`@Param()`注解
<mappers>
  <mapper class="com.cwx.dao.UserMapper"/><!--这里用的是class,以前是用resources-->
</mappers>

Mybatis执行流程(分析源码)

数据关系之多对一查询

举例:有个student实体类,包含id,name,Teacher(老师的对象)多个学生对应一个老师,要求查出所有学生和(一个)老师

<!--方式一(常用): 按照结果嵌套处理 -->
<select id="getStudent" resultMap="StudentTeacher">
  select s.name sname,s.id sid,t.name tname 
  from student s ,teacher t 
  where s.tid=t.id;
</select>
<resultMap id="StudentTeacher" type="Studenet">
  <result property="id" column="sid">
  <result property="name" column="sname">
  <association property="teacher" javaType="Teacher">
   <result property="name" column="sname">
  </association>
</resultMap>
<!--方式二: 按照查询方式处理 -->
<select id="getStudent" resultMap="StudentTeacher2">
  select * from student
</select>
<resultMap id="StudentTeacher2" type="Student">
  <association property="teacher" column="tid" javaType="Teacher" select="getTeacher">
</resultMap>
<select id="getTeacher" type="Teacehr">
  select * from Teacher where id =#{tid}
</select>

总结:主要是利用了<association>,当要查询的东西属于多的一方用<association>,当要查询的东西属于一的一方用collection

数据关系之一对多查询

还是上面的例子,这次的角度站在老师这一方,就是一对多关系,Student类中的teacher对象,变为tid,Teacher类加一个List<Student>对象。

<!--方式一:按照结果嵌套处理-->
<select id="getTeacher" resultMap="TeacherStudent">
  select s.name sname,s.tid stid,t.id tid, t.name tname
  from sutdent s,teacher t
  where t.id=s.tid and t.id=#{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
  <result property="name" column="tname">
  <result property="id" column="tid">
  <collection property="student" ofType="Studnet"><!--这里区别是使用了ofType,为了识别集合中的类型-->
    <result property="name" cloumn="sname">
    <result property="id" cloumn="sid">
  </collection>
</resultMap>
<!--方式:按照查询方式嵌套处理-->
<select id="getTeacehr" resultMap="TeacherStudent2">
  select * from teacher where id=#{tid}
</select>
<resultMap id="TeacherStudent2" type="Teacher"> 
 <!--这里的column=id是为了给下面的条件用的id传值-->
  <collection property="student"  javaType="ArrayList" ofType="Student" select="getStudent" column="id">
</resultMap>
<select id="getStudent" type="Student">
  select * from student where id =#{tid}
</select>

数据关系之多对多查询

思路:利用中间表
【面试高频】

动态SQL

<select id="quryBlogIf" type="Blog" parameType="map"><!--这里的参数是map类型,有可能会传多个值-->
  select * from Blog where state  ='ACTIVE'
  <if test="title !=null">
    and titile=#{title}
  </if>
  <if test="author!=null">
    and author=#{author}
  </if>
</select>

缓存

Mybatis缓存

一级缓存

二级缓存

二级缓存开启前先要保证Mybatis是否开启了全局缓存,全局缓存默认是开启的。

Tips:我们要将实体类序列化,实现Serializable接口,不然会报错NoSerializableException

Mybatis缓存原理

上一篇下一篇

猜你喜欢

热点阅读