mybatis介绍与开发

一 Mybatis简介

Mybatis是持久层的框架,主要在Java中用于操作数据库,相比于原始的JDBC和DBUtils等手段方法,Mybatis将复杂的加载驱动,创建连接等操作封装起来,让使用者不必烦心于重复的细节,只需要关注sql语句本身,进行一些配置就可以完成对数据库的增删改查。

二 Mybatis使用方法与流程

1 使用前的准备

可连接的数据库如本地或远程的MySQL,配置好Maven与其他必要内容的idea软件

2 简易demo入门

这是一个使用mybatis框架,从数据库中查询用户信息并且封装到对象列表,并且输出的demo。
具体步骤如下:

1.创建maven工程,在Maven中导入必要的依赖

  maven中导入坐标如下

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--引入lombok的依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--mybatis的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.6</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.6</version>
        </dependency>
    </dependencies>

其中,mysql和mybatis是必须导入的,junit是为了测试,lombok是为了使用其注释,简化pojo中的代码编写,下面几个是为了和resource中的log4j文件一起输出mybatis的日志。

2.创建pojo类

上面三个注解可以生成各种需要的函数,getter,setter等等

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int uid;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
}

 

3.创建dao接口

查找数据库表中的所有数据

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

  

4.创建dao的映射文件

<?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.example.dao.UserDao">

    <select id="findAll" resultType="com.example.pojo.User">
        select * from t_user
    </select>

</mapper>

 

5.创建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 resource="jdbc.properties"></properties>

    <typeAliases>
        <package name="com.example.pojo"/>
    </typeAliases>

    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="driver" value="${jdbc.driver}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.example.dao"/>
    </mappers>
</configuration>

 

6.测试

public class SqlSessionFactoryUtils {
    private static InputStream is;
    private static SqlSessionFactory sessionFactory;

    static {
        try {
            //1. 创建SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //2. 读取核心配置文件,转换成字节输入流
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //3. 创建SqlSessionFactory对象
            sessionFactory = sqlSessionFactoryBuilder.build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取SqlSession对象的方法
     * @return
     */
    public static SqlSession openSession(){
        SqlSession sqlSession = null;
        try {
            //4. 创建SqlSession对象
            sqlSession = sessionFactory.openSession();
            is.close();
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
        return sqlSession;
    }

    /**
     * 提交事务并且关闭资源
     * @param sqlSession
     */
    public static void commitAndClose(SqlSession sqlSession){
        sqlSession.commit();
        sqlSession.close();
    }

    /**
     * 回滚事务并且关闭资源
     * @param sqlSession
     */
    public static void rollbackAndClose(SqlSession sqlSession){
        sqlSession.rollback();
        sqlSession.close();
    }
}
public class MybatisTest {
    @Test
    public void test(){
        SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
        UserDao userDao = sqlSession.getMapper(UserDao.class);

        List<User> userList = userDao.findAll();
        for (User user : userList) {
            System.out.println(user);
        }

        SqlSessionFactoryUtils.commitAndClose(sqlSession);
    }
}

此外,jdbc.properties这样写,

jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.driver=com.mysql.jdbc.Driver
当项目搭建完成后,项目结构如图
 运行test(),生成结果如下,成功在jdbc.properties中表示的mysql数据库t_user表中查找到所有数据,并且封装后输出。
 

3.代码解读

1.mybatis的核心配置文件

最上方是固定约束,<configuration>标签表示这是配置,

<environments>,配置连接环境,既数据库的驱动,数据库地址,用户名,密码,其中可以写多个<environment>标签,选用与id与default相同的。POOLED表示要池化,

<mapper>,配置mapper代理配置文件的位置,引入映射文件,此次使用package标签,直接扫描指定包内的所有daoxml文件。

<properties>,引入外部properties文件,数据源配置中的${jdbc.driver}就来源于此,也可以不使用<properties>,直接写入数据源,但这样耦合度太高,不方便使用修改。

typeAliases,为映射文件中的数据类型配置别名,建议直接使用package包扫描自动读取。

2 mapper xml文件

最上方固定约束

<mapper>表示对应dao中的一个接口,namespace应该写对应dao文件的地址。

<select>对应接口中的一个方法,id与方法名相同,resultType表示输出结果类型,parameterType表示参数类型。

注意,Mapper接口开发需要遵循以下规范:

  1. 存储路径建议和对应的Dao接口保持一致

  2. 文件名建议和对应Dao接口的名字保持一致

  3. 配置文件的根标签的namespace属性必须和对应的Dao接口的全限定名保持一致

  4. 接口中的每一个方法,就对应映射配置文件中的一个标签:

    1. 查询方法,对应select标签

    2. 添加方法,对应insert标签

    3. 删除方法,对应delete标签

    4. 修改方法,对应update标签

  5. 映射配置文件中的标签的id属性,就必须和对应的方法的方法名保持一致

  6. 映射配置文件中的标签的parameterType属性,必须和对应的方法的参数类型(全限定名)保持一致

  7. 映射配置文件中的标签的resultType属性,必须和对应的方法的返回值类型(全限定名)保持一致,但是如果返回值是List则和其泛型保持一致

 

 

三 Mybatis的其他要掌握的知识

1 如何获取自增长的键值

insert时,要想获得自增长的键值,要在其中这样修改

 <!--parameterType属性: 参数的类型 ;  赋值的时候直接写对象里面的属性名-->
    <insert id="save" parameterType="com.itheima.bean.User">
        <!--resultType: 主键类型; keyProperty:pojo里面对应的id的属性名; order属性: 指定是在目标的sql语句之前还是之后执行 -->
        <selectKey resultType="int" keyProperty="uid" order="AFTER">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO t_user(username,sex,birthday,address)VALUES(#{username},#{sex},#{birthday},#{address})
    </insert>

2 模糊查询

<select id="findByFirstName02" parameterType="string" resultType="User">
        <!--select * from t_user where username like "%"#{username}"%"-->
        <!--select * from t_user where username like concat("%",#{username},"%")-->
        select * from t_user where username like "%${username}%"
</select>

parameterType细节

  1传递简单类型,如基本的类型,字符串,直接写`#{任意字符串}`或者`'${value}'`

  2传递 pojo 对象 或者 Map,#{}或者'${}'括号中的值为 pojo 属性名称或者Map的key。

  3传递 pojo 包装对象类型

  开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。Pojo 类中包含 pojo。如#{user.username}

4resultType深入

  1. 输出简单类型 直接写 java类型名 eg: int

  2. 输出pojo对象 直接写 pojo类型名 eg: User

  3. 输出pojo列表类型 写 列表里面的泛型的类型 eg: List<User> 写User

5resultMap

resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

    <select id="findByUid" parameterType="int" resultMap="findByUidMap">
        select uid uid_,username username_ ,birthday birthday_ ,sex sex_ ,address address_  from t_user where uid = #{id}
    </select>

    <resultMap id="findByUidMap" type="com.itheima.bean.User">
        <id property="uid" column="uid_"></id>
        <result property="username" column="username_"></result>
        <result property="birthday" column="birthday_"></result>
        <result property="sex" column="sex_"></result>
        <result property="address" column="address_"></result>
    </resultMap>
<!-- 
id:此属性表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个id。
type: 当前resultMap封装后返回的结果
property:表示 User 类的属性。
column:表示 sql 查询出来的字段名。(column 和 property 放在一块儿表示将 sql 查询出来的字段映射到指定的 pojo 类属性上。)
-->
<mapper namespace="com.itheima.dao.AccountDao">
    <!--
        使用resultMap标签自定义映射规则
    -->
    <resultMap id="accountUserMap" type="Account">
        <id column="aid" property="aid"></id>
        <result column="money" property="money"></result>
        <result column="uid" property="uid"></result>

        <!--
            要进行一对一的映射配置
            property表示要映射的pojo的属性名
            javaType表示要进行映射的POJO的属性的类型
        -->
        <association property="user" javaType="User">
            <result column="uid" property="uid"></result>
            <result column="username" property="username"></result>
            <result column="sex" property="sex"></result>
            <result column="birthday" property="birthday"></result>
            <result column="address" property="address"></result>
        </association>
    </resultMap>
    <select id="findAccountUserByAid" parameterType="int" resultMap="accountUserMap">
        select * from t_account a,t_user u where a.uid=u.uid and a.aid=#{aid}
    </select>
</mapper>
<mapper namespace="com.itheima.dao.UserDao">
    <!--
        使用resultMap标签,自定义映射规则
    -->
    <resultMap id="userAccountMap" type="User">
        <id column="uid" property="uid"></id>
        <result column="address" property="address"></result>
        <result column="username" property="username"></result>
        <result column="sex" property="sex"></result>
        <result column="birthday" property="birthday"></result>
        <!--
            使用collection标签进行一对多映射
        -->
        <collection property="accountList" ofType="Account">
            <result column="aid" property="aid"></result>
            <result column="money" property="money"></result>
            <result column="uid" property="uid"></result>
        </collection>
    </resultMap>
    <select id="findUserAccountByUid" parameterType="int" resultMap="userAccountMap">
        select * from t_user u,t_account a where a.uid=u.uid and u.uid=#{uid}
    </select>
</mapper>

6 延迟加载

就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.

​ 坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。

​ 好处: 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快.

SQL 深入 动态语句

1 if

<select id="findByAddress" resultType="LinkMan" parameterType="string">
    select * from linkman
    <!--
    加入判断,使用if标签判断
    -->
    <if test="address != null and address.length > 0">
    where address=#{address}
    </if>
</select>

2 where

<select id="findByAddressAndSex" resultType="LinkMan" parameterType="LinkMan">
    select * from linkman
    <!--
            where标签的作用是,如果有if条件成立,则会在SQL语句中添加WHERE关键字
            而且还会自动去掉第一个条件的and
        -->
    <where>
        <!--
                判断,如果address不为空,则添加address的条件
                如果sex不为空,则添加sex的条件
            -->
        <if test="address != null and address.length > 0">
            and address=#{address}
        </if>
        <if test="sex != null and sex.length > 0">
            and sex=#{sex}
        </if>
    </where>
</select>

3foreach

<delete id="deleteByIds" parameterType="int">
    delete from linkman
    <!--
            使用foreach标签进行遍历
            collection属性就是要遍历的对象,如果要遍历的对象是一个集合,就写list
            item属性就是遍历出来的每一个元素
            index属性就是遍历出来的每一个元素的下标
            separator属性就是分隔符
            open属性 表示在遍历出来的第一个元素之前拼接字符串
            close属性 表示在遍历出来的最后一个元素之后拼接字符串
        -->
    <foreach open="where id in(" close=")" collection="list" item="id" index="i" separator=",">
        #{id}
    </foreach>
</delete>

4 include

<sql id="selectAll">
    select id,name,sex,age,qq,email,address from linkman
</sql>
<select id="findById" parameterType="int" resultType="LinkMan">
    <include refid="selectAll"></include>
    where id=#{id}
</select>

四 了解

1Mybatis 连接池与事务

2MyBatis缓存

3MyBatis注解开发

 

 

附:mybatis知识点总结图

posted @ 2021-08-03 22:10  春华_秋实  阅读(102)  评论(0)    收藏  举报