欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Mybatis的基础配置

程序员文章站 2022-05-04 08:48:57
一.基础配置1.1xml配置环境pom.xml文件

一.基础配置

1.1xml配置环境

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
             <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>
    <artifactId>day02_eesy_01mybatisCRUD</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>

src/main/resources/MybatisConfig.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>

    <properties resource="jdbcConfig.properties"></properties>
    
	<!--为该包下的类取别名,配置dao的时候不用写全类名了-->
    <typeAliases>
        <package name="com.itheima.domain"></package>
    </typeAliases>

    <!--配置环境-->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"></transactionManager>

            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <mapper resource="com/itheima/dao/IUserDao.xml"/>     
    </mappers>
</configuration>

1.2编写代码

dao接口

package com.itheima.dao;

import com.itheima.domain.User;

import java.util.List;

public interface IUserDao {
    /**
     * 查询所有操作
     */
    List<User> findAll();
}

src/main/resources/对应的dao的路径/dao.xml

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--namespace绑定一个对应的mapper接口-->
<mapper namespace="com.itheima.dao.IUserDao">
    <!--配置查询所有-->
    <select id="findAll" resultType="com.itheima.domain.User">
        select * from user
    </select>
</mapper>

test文件

public class MybatisTest {
    /**
     * 入门案例
     * @param args
     */
    public static void main(String[] args) throws Exception {
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建一个SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);

        //3.使用工厂生产一个SqlSession对象
        SqlSession session = factory.openSession();
        //4.使用SqlSession创建Dao的代理对象
        IUserDao userDao = session.getMapper(IUserDao.class);
        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
        //6.释放资源
        session.close();
        in.close();
    }
}

1.3.注解配置:

dao接口:

public interface IUserDao {
    /**
     * 查询所有操作
     */
    @Select("select * from user")
    List<User> findAll();

    @Select("select * from user where id = #{em}")
    User getUserById(int id);

    @Select("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
    void saveUser(User user);
}

mybatisConfig.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">
                <!--配置连接池的四个基本信息-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="admin"/>
            </dataSource>
        </environment>
    </environments>
    <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
    如果是用注解来配置,此处应该使用class属性指定被注解的dao全限定类名
    -->
    <mappers>
        <mapper class="com.itheima.dao.IUserDao"/>
    </mappers>
</configuration>

二.Mybatis全局配置文件讲解

2.1全局配置文件的类容和顺序

Properties(属性):通过该标签来读取java配置信息(jdbc.properties)
Settings(全局参数设置):一般我们使用使用该标签来开启二级缓存和懒加载。
typeAliases(类型别名):在编写sql语句的时候不用在使用全类名了
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境信息集合)
-environment(单个环境信息)
–transactionManager(事务)
–dataSource(数据源)
mappers(映射器):该标签的作用是加载映射文件

2.2 详解

Properties标签

作用:引入外部资源文件

jdbcConfig.properties:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useSSL=false
jdbc.username=root
jdbc.password=admin
<?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="jdbcConfig.properties"></properties>
    
    <typeAliases>
        <package name="com.itheima.domain"></package>
    </typeAliases>

    <!--配置环境-->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"></transactionManager>

            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    
    <!-- 配置映射文件的位置 -->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

settings标签

一般用于开启懒加载和二级缓存

    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
		<!--开启缓存,还要再对应的dao.xml中开启-->
		<setting name="cacheEnabled" value="true"/>
    </settings>

typeAliases标签

作用:该标签是对po类进行别名设置,这样,在后面使用po类的时候就可以直接通过别名引用,而不需要通过po类的全限定名来引用。这样可以提高我们的开发效率。

mappers标签

作用:加载配置文件(xml,或者注解)

方法一:引入xml

   <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
    <mappers>
        <mapper resource="com/itheima/dao/IUserDao.xml"/>
    </mappers>

方法二:引入注解

    <mappers>
        <mapper class="com.itheima.dao.IUserDao"/>
    </mappers>

方法三:引入整个包下的

    <!-- 配置映射文件的位置 -->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>

三:映射文件

3.1:parameterType

第一种:简单类型

 <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="user" >
        select * from user where id = #{uid}
    </select>

此时#{}内可以随意填写

第二种:pojo类型

    <!--更新用户信息-->
    <update id="updateUser" parameterType="user">
        update user set username=#{username},address=#{address} where id=#{id}
    </update>

此时#{}里面的必须和user内部的属性名对应

第三种:包装类

先创建一个包装类,包装user对象

public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}
    <!--根据QueryVo的条件查询用户-->
    <select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User">
        select * from user where username like #{user.username};
        <!--注意这个user的名字不能瞎写,要和QueryVo里面的user属性同步,这个user属性里面才有username属性-->
    </select>

注意:#{}和${}的区别

1.#{}表示占位符?,parameterType接收简单类型的参数时,里面的名称可以任意。
2.${}表示拼接符,parameterType接收简单类型的参数时,里面的名称必须是value

大家可以试试看下面两个的区别:原地址

SELECT * FROM #{tableName} 
SELECT * FROM ${value}

在模糊查询中:

 select * from user where username like #{lala};
    <!--方法二:   select * from user where username like '%${value}%';--><!--里面固定为value-->

3.2:resultType

resultType结果映射要求:需要查询结果的列名和映射的对象的属性名一致,这样才能映射成功。如果映射没成功也不会报错,只是映射结果中对象的相应属性没有值,为空。如果映射的列名和对象中的属性名全部不一致,那么映射的对象为空。如果在使用sql语句查询的时候给查询结果列设置了别名,则别名要和映射结果对象的属性名一致,这样才能保证映射成功。

第一种:简单类型

	<select id="findUserCount" resultType="int">
		select count(*) from user;
	</select>

第二种:pojo类型

    <!--查询用户-->
    <select id="findUser" parameterType="int" resultType="com.itheima.domain.User">
        select * from user where id=#{uid};
    </select>

3.3:resultMap

作用:使用resultMap结果映射时,不需要查询出来的结果集的列名和映射结果对象的属性名相同,但是需要声明一个resultMap,手动的方式来对列名和对象属性进行映射。(或者可以在sql语句种取别名,是查询结果和pojo属性名字一致)

映射文件添加查询语句:
[id]:定义resultMap的唯一标识

[type]:定义该resultMap最终映射的pojo对象

[id标签]:映射结果集的唯一标识列,如果是多个字段联合唯一,则定义多个id标签

[result标签]:映射结果集的普通列

[column]:SQL查询的列名,如果列有别名,则该处填写别名

[property]:pojo对象的属性名。

user类:

public class User implements Serializable {

    private Integer userId;
    private String userName;
    private String userAddress;
    private String userSex;
    private Date userBirthday;
    .....}
    <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
    <resultMap id="userMap" type="uSeR">
        <!-- 主键字段的对应 -->
        <id property="userId" column="id"></id>
        <!--非主键字段的对应-->
        <result property="userName" column="username"></result>
        <result property="userAddress" column="address"></result>
        <result property="userSex" column="sex"></result>
        <result property="userBirthday" column="birthday"></result>
    </resultMap>

3.4动态sql

3.4.1:if语句

dao.xml中

    <!--根据条件查询-->
  <select id="findUserByCondition" resultMap="userMap" parameterType="user">

        select * from user where 1=1
        <if test="userName != null">
            and username = #{userName}
        </if>
        <if test="userSex != null">
            and sex = #{userSex}
        </if>

        <!--      select * from user
              <where>
                  <if test="userName != null">
                      and username = #{userName}
                  </if>
                  <if test="userSex != null">
                      and sex = #{userSex}
                  </if>
              </where>-->
    </select>

这里有1=1或者where标签所以即使条件为null,WHERE后面也不会报错。

Test类中:

    @Test
    public void testFindByCondition(){
        User u = new User();
        u.setUserName("老王");
//        u.setUserSex("女");
        List<User> users = userDao.findUserByCondition(u);
        for(User user : users){
            System.out.println(user);
        }
    }

3.4.2:foreach语句

foreach用来遍历,遍历的对象可以是数组,也可以是集合。
相关属性:
Collection:collection属性的值有三个分别是list、array、map三种。
Open:前缀。
Close:后缀。
Separator:分隔符,表示迭代时每个元素之间以什么分隔。
Item:表示在迭代过程中每一个元素的别名。
Index:用一个变量名表示当前循环的索引位置。

    <!--根据queryvo中的id集合实现查询用户列表-->
    <select id="findUserInIds" resultMap="userMap" parameterType="queryvo">
        select * from user
        <where>

                <foreach collection="ids" item="uid" open="and id in (" separator=" or "  close=")"  >
                    #{uid}
                </foreach>

        </where>
    </select>

QueryVo类:

public class QueryVo {
    private User user;
    private List<Integer> ids;
}

Test类中:

    /**
     * 测试foreach标签的使用
     */
    @Test
    public void testFindInIds(){
        QueryVo queryVo = new QueryVo();
        ArrayList<Integer> list = new ArrayList<>();
        list.add(41);
        list.add(42);
        list.add(46);
        queryVo.setIds(list);
        List<User> users = userDao.findUserInIds(queryVo);
        for(User user : users){
            System.out.println(user);
        }
    }

四:x对x查询

背景:分别有account表和user表
一个user可以有多个账号。
一个账号只能对应一个user。

4.1:一对一查询

给账号查询user

  1. 思路一:创建一个类AccountUser继承Account,再定义user的字段,里面前面的方法进行封装,返回类型为AccountUser。
  2. 思路二:再在Account类中定义一个User属性。见下:

Account类:

public class Account implements Serializable {
    private Integer ID;
    private Integer uid;
    private double money;
    //从表实体应该包含一个主表实体的对象引用
    private User user;
}

Test类:

    @Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
        for(Account account : accounts){
            System.out.println("-----------每一个account的信息-------------------");
            System.out.println(account);
            System.out.println(account.getUser());
        }

    }

Dao.xml

    <!--定义封装的account和user的resultMap-->
    <resultMap id="accountUserMap" type="Account">
        <id property="ID" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--一对一的关系映射,配置封装user的内容-->
        <association property="user" column="uid" javaType="user">
            <id property="id" column="id"></id>
            <result column="username" property="username"></result>
            <result column="address" property="address"></result>
            <result column="sex" property="sex"></result>
            <result column="birthday" property="birthday"></result>
        </association>
    </resultMap>
    
    <!--查询所有账户,同时还要获取到当前账户的所属用户信息-->
    <select id="findAll" resultMap="accountUserMap">
        SELECT u.*,a.id AS aid, a.`money`,a.`uid` FROM account a,USER u WHERE a.`uid` = u.`id`
    </select>

4.2:一对多查询

User类:

public class User implements Serializable {

    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;
    //1对多关系映射:主表实体应该包含从表实体的集合引用
    private List<Account> accounts;
}

dao.xml

    <!--定义user的resultMap-->
    <resultMap id="userAccountMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <collection property="accounts" ofType="account">
            <id property="ID" column="aid"></id>
            <result property="uid" column="uid"></result>
            <result property="money" column="money"></result>
        </collection>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userAccountMap">
        SELECT u.* ,a.`ID` AS aid ,a.`money`,a.`uid` FROM USER u LEFT OUTER JOIN account a ON u.id = a.uid
    </select>

Test类:

    @Test
    public void testFindAll(){
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println("----------每个用户的信息-----------");
            System.out.println(user);
            System.out.println(user.getAccounts());
        }

    }

4.3:多对多查询

背景:role(角色表),user_role表,一个角色可以有多个人,一个人叶有多个角色。比如:演员(角色):胡歌,黄渤。胡歌(人):演员,歌手。
这样以看又变成了一对多了。。。。。略

五:懒加载

sql语句不一次性加载,用到了我就去执行,不然不执行。

MybatisConfig.xml中开启懒加载

    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    <!-- 查询所有 -->
    <select id="findAll" resultMap="userAccountMap">
        select * from user
    </select>

我执行下面的语句:

    @Test
    public void testFindAll(){
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println("----------每个用户的信息-----------");
            System.out.println(user);
            System.out.println(user.getAccounts());
        }
    }

没开启:
Mybatis的基础配置
开启:Mybatis的基础配置

六:缓存

6.1: 开启缓存

mybatisConfig.xml

    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

6.2:案例分析

第一种:同一个sqlSession开启的dao对象:

Mybatis的基础配置
只查询了一次,共用缓存

第二种:两个sqlSession开启的dao对象

Mybatis的基础配置
查询了两次,说明不同的sqlSession不共用缓存

第三种:当有缓存另一个来修改的时候

    @Test
    public void testMyIdeal(){
        User user1 = userDao.findById(49);
        System.out.println("userDao1更新前的user是"+user1);

        User user2 = userDao2.findById(49);
        System.out.println("userDao2更新前的user是"+user2);

        //更新user对象
        User userNew = new User();
        userNew.setUsername("马云");
        userNew.setId(49);
        userNew.setAddress("北京");

        userDao2.updateUser(userNew);
        User user2new = userDao2.findById(49);
        System.out.println("更新后userDao2的user是:" + user2new);
        System.out.println("更新后userDao1的user是"+user1);

        //查询查看
        User user3 = userDao.findById(49);
        System.out.println(user3);

    }

Mybatis的基础配置
若加上update的话,那么相当于六次结果,但只有4个查询语句。

session1在刷新之后重新打印user对象发现还是没修改前的样子。说明在session1有缓存的情况下,session2修个session1缓存中的那个对象,session1 会出现误读的情况,并且重新查询session1还是呆呆的以为自己的缓存仍然是好的。但是session2继续查询的话会执行查询语句,说明更新后会刷新当前session的缓存

本文地址:https://blog.csdn.net/qq_45595546/article/details/107484203

相关标签: mybatis