Mybatis个人总结

一、创建流程

1.导入依赖

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
    </dependencies>

2.创建工具类MybatisUtils

//简化版,不带线程池
public class MybatisUtils {
//
   private static SqlSessionFactory sqlSessionFactory;
    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;

        try {
            inputStream = Resources.getResourceAsStream(resource);
            //此时sqlSessionFactory不要使用SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);语句,
            //此时会使用重新定义的sqlSessionFactory,而未将数据注册到外部的private static SqlSessionFactory sqlSessionFactory的资源中,此时会提示空指针异常
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession() {
              return sqlSessionFactory.openSession();
    }

    public static  void closeSqlSession() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.close();
    }

```java
//带线程池
   public class MybatisUtils { private static ThreadLocal<SqlSession> localSessions = new ThreadLocal<SqlSession>();
    static {
        InputStream inputStream = null;
        String resource = "mybatis-config.xml";

        try {
            // 加载Mybatis的配置文件
             inputStream =Resources.getResourceAsStream(resource);
            // 创建SqlSessionFactory对象.
            factory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if ( inputStream != null) {
                try {
                     inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
        // 获取Session对象
    public static SqlSession getSession() {
        SqlSession session = localSessions.get();
        if (session == null) {
            session = factory.openSession();
            localSessions.set(session);
        }
        return session;
    }

    // 关闭session的方法
    public static void closeSession() {
        SqlSession session = localSessions.get();
        if (session != null) {
            session.close();
            localSessions.remove();
        }
    }
}

3.创建工具类的配置文件mybatis-config.xml及可能遇到的问题

<?xml version="1.0" encoding="UTF8" ?>
<!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/mybatis?useSSL=true&amp;serverTimezone=GMT%2B8&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/mybatis/dao/UserMapper.xml"/>
    </mappers>
</configuration>
  • 若提示1字节的UTF-8序列的字节1无效的问题处理,可将

    <?xml version="1.0" encoding="UTF-8" ?>改为<?xml version="1.0" encoding="UTF8" ?>
    
  • List item

4.创建实体类

package com.mybatis.pojo;

public class User {
    private  Integer id;
    private String name;
    private  String password;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public User() {
    }

    public User(Integer id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }
}

5.创建接口UseDao

接口中指定了方法名称

package com.mybatis.dao;

import com.mybatis.pojo.User;

import java.util.List;

public interface UserDao {
    List<User> getUserList();
}

6.创建接口UseDao对应的UserMapper.xml配置文件

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.mybatis.dao.UserDao">
     <select id="getUserList" resultType="com.mybatis.pojo.User">
    select * from mybatis.user
  </select>
</mapper>

7.创建测试类

public class MybatisUtilsTest {
 @Test
    public void getSqlSession() {
        SqlSession session = null;
        try {
            session = MybatisUtils.getSession();
            UserDao mapper = session.getMapper(UserDao.class);
            List<User> userList = mapper.getUserList();
            for (User user : userList) {
                System.out.println(user);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
           session.close();
        }
}
  • 若提示找不到配置文件,则在pom.xml文件中配置如下信息
<build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

二、模糊查询

<select id="getUserLike" resultType="com.mybatis.pojo.User">
        select * from mybatis.user where name like "%"#{value}"%"
</select>

避免通配符写在参数中

    @Test
    public void getUserLike() {
        SqlSession session = MybatisUtils.getSqlSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        //避免通配符写在参数中,下列所示
        List<User> userLike = mapper.getUserLike("%add%");
        for (User user : userLike) {
            System.out.println(user);
        }
        session.close();
    }

三、configuration(配置)

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

properties(属性)

方法一:直接引入外部文件

  1. 在 properties 元素的子元素中设置,通过database.properties文件
 driver =com.mysql.cj.jdbc.Driver
 url =jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;serverTimezone=GMT%2B8&amp;useUnicode=true&amp;characterEncoding=utf8
 username =
 password =
  1. 在配置文件中引入
//config.xml文件中标签顺序如下,否则会报错
//<?xml version="1.0" encoding="UTF-8"?>
//<configuration><!--配置-->
//	<properties/><!--属性-->
//	<settings/><!--设置-->
//	<typeAliases/><!--类型别名--> 
//	<typeHandlers/><!--类型处理器--> 
//	<objectFactory/><!--对象工厂-->  
//	<plugins/><!--插件--> 
//	<environments><!--配置环境--> 
//		<environment><!--环境变量--> 
//		<transactionManager/><!--事务管理器--> 
//			<dataSource/><!--数据源--> 
//		</environment>
//	</environments>
//	<databaseidProvider/><!--数据库厂商标识-->  
//	<mappers/><!--映射器--> 
//</configuration>
<configuration>
    <properties resource="db.properties"></properties>
</configuration>
  1. 在整个配置文件中用来替换需要动态配置的属性值
<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

方法二:核心配置文件中直接引入

<configuration>
    <properties resource="db.properties">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;serverTimezone=GMT%2B8&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="123"/>
                <property name="password" value="321"/></properties>
</configuration>

注意:如果两个文件有同一个字段,优先使用后外部配置文件

settings(设置)

Column 1Column 2Column 3Column 4
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true /falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true/ falsefalse
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J / LOG4J/ LOG4J2 /JDK_LOGGING/ COMMONS_LOGGING / STDOUT_LOGGING /NO_LOGGING未设置

typeAliases(类型别名)

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

方法一:在核心配置文件中引入

   <typeAliases>
        <typeAlias type="com.mybatis.pojo.User" alias="User"></typeAlias>
    </typeAliases>

方法二:指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

   <typeAliases>
        <package name="com.mybatis.pojo"/>
    </typeAliases>
//在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名
//若有注解,则别名为其注解值。创建实体类时:
@Alias("user")
public class User {
    ...
}
    //com.mybatis.pojo.User别名为user

建议:
实体类较少,使用方法一,可以自定义别名
实体类较多,使用方法二,添加注解可以自定义别名

常见的 Java 类型内建的类型别名。它们都是不区分大小写的。
注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator

environments(环境配置)

    MyBatis 可以配置成适应多种环境,不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境.
environments 元素定义了如何配置环境。

environment(环境变量)

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <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>
    注意一些关键点:

    默认使用的环境 ID(比如:default="development")。
    每个 environment 元素定义的环境 ID(比如:id="development")。
    事务管理器的配置(比如:type="JDBC")。
    数据源的配置(比如:type="POOLED")。

transactionManager(事务管理器)

事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。

MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。

!!!提示:如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

dataSource(数据源)

 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。
 有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]")。

mappers(映射器)

方法一(推荐):

<!-- 使用相对于类路径的资源引用 -->
<mappers>
 <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
 </mappers>

方法二:

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
    </mappers>

注意:

  • 接口和他的Mapper配置文件必须同名
  • 接口和他的Mapper配置文件必须在同一包下

方法三:

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers

注意:

  • 接口和他的Mapper配置文件必须同名
  • 接口和他的Mapper配置文件必须在同一包下

作用域(Scope)和生命周期

错误的使用会导致非常严重的并发问题。

SqlSessionFactoryBuilder:

  • 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了
  • SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。

SqlSessionFactory:

  1. SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
  2. SqlSessionFactory 的最佳作用域是应用作用域。
  3. 想象为数据库连接池
  4. 最简单的就是使用单例模式或者静态单例模式。

SqlSession:

  1. 连接到连接池的请求
  2. 每个线程都应该有它自己的 SqlSession 实例。
  3. SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
  4. 用完之后关闭,否则占用资源

四、解决属性名和字段名不一致的问题

结果映射

  1. resultMap 元素是 MyBatis 中最重要最强大的元素。
  2. ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

五、Log4j

1.导包

    <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
  1. 核心配置文件中设置
//严格大小写和空格
<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>
  1. 日志文件级别
//UserMapperTest.class为当前类.class
    Logger logger = Logger.getLogger(UserMapperTest.class);
    logger.info("info");
    logger.debug("debug");
    logger.error("error");

六、使用注解

关于接口的理解

  • 接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离

  • 接口的本身反映了系统设计人员对系统的抽象理解

  • 接口应有两类:
    - 第一类是一个个体的抽象,它可对应一个抽象实体(abstract.class)
    - 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface)

  • 一个个体可能有多个抽象面,抽象体与抽象面是有区别的

//使用class进行加载,且接口文件同.xml文件必须在同一个包下
<mappers>
    <mapper class="com.mybatis.dao.UserMapper"></mapper>
</mappers>

关于@Param()注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要添加
  • 如果只有一个基本类型,可以忽略,建议添加
  • SQL中的引用就是@Param()中设定的属性名
public interface UserMapper {
@Select("select * from user")
List<User> getUser();
@Select("select * from user where id=#{id}")
User getUserById(@Param("id") int id);
@Insert("insert into user (id,name,password) values (#{id},#{adminName},#{adminPassword})")
    int addUser(User user);
}

${}和#{}的区别

原sql语句:

delete from
ups_role_permission_dataparams
where role_id = #{roleId,jdbcType=INTEGER}

在这里用到了#{},使用#时:

1、用来传入参数,sql在解析的时候会加上" ",当成字符串来解析 ,如这里 role_id = “roleid”;

2、#{}能够很大程度上防止sql注入;

延伸:

1、用${}传入数据直接显示在生成的sql中,如上面的语句,用role_id = ${roleId,jdbcType=INTEGER},那么sql在解析的时候值为role_id = roleid,执行时会报错;

2、${}方式无法防止sql注入;

3、$一般用入传入数据库对象,比如数据库表名;

4、能用#{}时尽量用#{};

七、LomBok

  1. 下载插件
  2. 导入jar包
  3. 实体类上加注解
IntelliJ Lombok plugin

GitHub | Issues | Donate ( PayPal )  

A plugin that adds first-class support for Project Lombok 

Features
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
@ExtensionMethod (Experimental, activate manually in plugin settings)
Lombok config system
Code inspections
Refactoring actions (lombok and delombok)
@Data
无参/get/set/euqals/hashCode/toString
@AllArgsConstructor
有参方法,会覆盖掉@Data中的无参方法
@NoArgsConstructor
单独添加无参方法

八、查询

多对一

按照查询嵌套处理

<mapper namespace="com.mybatis.dao.StudentMapper">
    <resultMap id="StudentsTeacher" type="Student">
        <result property="id" column="id"></result>
        <result property="name" column="name"></result>
        //association
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacherById"></association>
    </resultMap>
    <select id="getStudents" resultMap="StudentsTeacher">
        select * from student
    </select>
    //此方法不用在接口中创建
    <select id="getTeacherById" resultType="Teacher">
                 select * from teacher where id=#{id}
    </select>
</mapper>

一对多

按照查询嵌套处理

<select id="getTeacher" resultType="Teacher">
    select * from teacher;
</select>
    <resultMap id="teacherStudent" type="Teacher">
        <result  property="id" column="tid"></result>
        <result property="name" column="tname" ></result>
        //collection
        <collection property="students"  ofType="Student">
            <result property="id" column="sid"></result>
            <result property="name" column="sname"></result>
            <result property="tid" column="tid"></result>
        </collection>
    </resultMap>
    <select id="getTeacherStudent" resultMap="teacherStudent">
        select s.id sid,s.name sname,t.name tname,t.id tid from student s,teacher t where s.tid=t.id and t.id=#{tid}
    </select>
  1. 关联-association 多对一
  2. 集合-collection 一对多
  3. JavaType用来指定实体类中属性的类型
  4. ofType用来指定映射到List后者集合中的pojo类型,泛型中的约束类型

九、动态SQL

if 语句

<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog where
   <if test="title != null">
      title = #{title}
   </if>
   <if test="author != null">
      and author = #{author}
   </if>
</select>
 HashMap<String, String> map = new HashMap<String, String>();
   map.put("title","Mybatis");
   map.put("author","MBP");
  • 同时使用map注入参数相当于&&
  • 如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询
    select * from blog where title = #{title} and author = #{author}

Where标签

  • “where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以 AND 或OR 开头的,则它会剔除掉。
<select id="queryBlogIf" 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>
  • 这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

Set标签

  • 当 update 语句中没有使用 if 标签时,如果有一个参数为 null,都会导致错误。
  • 当在 update 语句中使用if标签时,如果前面的if没有执行,则或导致逗号多余错误。
  • set标签可以将动态的配置 SET 关键字,并剔除追加到条件末尾的任何不相关的逗号。
  • 使用 if+set 标签修改后,如果某项为 null 则不进行更新,而是保持数据库原值。
<!--注意set是用的逗号隔开-->
<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标签

//可以代替where标签
<trim prefix="WHERE" prefixOverrides="AND | OR"></trim>
  //可以代替set标签
<trim prefix="SET" suffixOverrides=","></trim>

choose语句

  • choose语句类似于 Java 的 switch 语句,查询条件有一个满足即可
<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 views = #{views}
           </otherwise>
       </choose>
   </where>
</select>

SQL片段

  • 有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
  • 提取SQL片段:
<sql id="if-title-author">
   <if test="title != null">
      title = #{title}
   </if>
   <if test="author != null">
      and author = #{author}
   </if>
</sql>
  • 引用SQL片段:
<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
       <include refid="if-title-author"></include>
       <!-- 在这里还可以引用其他的 sql 片段 -->
   </where>
</select>
  • 注意:
  • 最好基于 单表来定义 sql 片段,提高片段的可重用性
  • 在 sql 片段中不要包括 where,一般只有if判断
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值