MyBatis笔记(idea版-xml配置方式)

MyBatis对比Hibernate

Hibernate:全自动映射,虽然方便,但是缺少灵活性,后期还要深入学hql,麻烦。
MyBatis:半自动映射,sql语句写在配置文件中,由开发人员人员控制。

Mybatis也是轻量级框架
Mybatis实现sql语句定制化,其他流程还是自动化,是结余Hibernate和JDBC之间的半自动框架。

mybatis的环境搭建

创建一个maven项目
pom文件的常用依赖

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.42</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>

小注意:
选成自己下载的maven
在这里插入图片描述
要打勾的地方
在这里插入图片描述
数据库
在这里插入图片描述
实体类(省略了get和set方法)

 private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

核心配置文件(必须要)

<?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的主配置文件 -->

```java
<configuration>
 <!-- 配置properties-->
    <properties resource="jdbcConfig.properties"></properties>
    
     <!--配置参数-->
    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"></setting>
    </settings>
    
  <typeAliases>
    <!--typeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名就再区分大小写 
    <typeAlias type="home.sise.cn.domain.User" alias="user"></typeAlias>-->
 <!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
    <package name="home.sise.cn.domain"></package>
</typeAliases>

    <!-- 配置环境 -->
    <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_day01"/>
                <property name="username" value="root"/>
                <property name="password" value="3997"/>-->

                <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>

    <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
   <!--<mapper resource="home/sise/cn/dao/IUserDao.xml"></mapper>-->
        <!-- package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class-->
        <package name="home.sise.cn.dao"></package>
</configuration>

连接池的属性有三个

POOLED 使用了连接池(常用)
UNPOOLED 没有使用连接池,每次请求都会创建一个链接
JNDI 需要通过服务器加载,必须是web工程或maven的war工程才能使用

mapper标签的属性
resource 用于配置xml方式
class 用于注解方式
package 直接指定dao接口包

typeAlias标签表示起别名

URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
URL用法:
http://localhost:8080/mybatis/ServletTest
协议 主机 端口 URI

在用户和账户的关联关系中,查询用户时,该用户的账户信息应该用的时候再查询。而查询账户时,该账户所属的用户信息应该一起查询出来。

延迟加载:不用的时候不查询。按需加载
立即加载:只要一调用方法,马上发起查询。

一对多,多对多:通常情况下我们都是采用延迟加载。
多对一,一对一:通常情况下我们都是采用立即加载。

配置properties
可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
resource属性: 常用的

jdbcConfig.properties配置文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_day01
jdbc.username=root
jdbc.password=3997

mybatis的代理方式(常用)

映射配置文件(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="home.sise.cn.dao.IUserDao">
    <select id="findAll" resultType="home.sise.cn.domain.User">
     select * from user
    </select>
</mapper>

使用代理方式小注意:
1.mybatis的映射配置文件位置必须和dao接口的包结构相同
2.映射配置文件的mapper标签的namespace属性的取值要和dao接口的全限定类名相同
3.映射配置文件的select标签的id属性要和dao接口的方法名相同
原因
mabatis在创建工厂加载解析xml配置文件时,是通过把映射配置文件中的namespace+id作为key,把sq语句和返回类型作为value放入了map集合中。在我们使用时,通过传入的接口的全限定名+方法名从放入的map集合中找到对应的信息,然后执行相应的操作。

客户代码
public class Mybatis_test {

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();
        SqlSession session = factory.openSession(true);
        //4.使用SqlSession创建Dao接口的代理对象
        IUserDao userDao = session.getMapper(IUserDao.class);
        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        } 
         //提交事务
       // session.commit();
        //6.释放资源
        session.close();
        in.close();
}}

使用了建造者模式,工厂方法模式,代理模式

SqlSession session = factory.openSession(true);
表示开启了自动提交事务

mybatis的接口实现方式

接口实现类

public class UserDaoImpl implements IUserDao {

    private SqlSessionFactory factory;

    public UserDaoImpl(SqlSessionFactory  factory){
        this.factory = factory;
    }


    public List<User> findAll(){
        //1.使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2.使用session执行查询所有方法
        List<User> users = session.selectList("home.sise.cn.dao.IUserDao.findAll");
        session.close();
        //3.返回查询结果
        return users;
    }
}

客户代码

public class MybatisTest {

    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.使用工厂创建dao对象
        IUserDao userDao = new UserDaoImpl(factory);
        //4.使用代理对象执行方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
        //5.释放资源
        in.close();
    }
}

mybatis的基本使用

常用增删改查

映射配置

```java
<?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.itheima.dao.IUserDao">

    <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
    <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>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userMap">
        select * from user;
    </select>
    
    <!-- 保存用户 -->
    <insert id="saveUser" parameterType="user">
        <!-- 配置插入操作后,获取插入数据的id -->
        <selectKey keyProperty="userId" keyColumn="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user(username,address,sex,birthday)values(#{userName},#{userAddress},#{userSex},#{userBirthday});
    </insert>

    <!-- 更新用户 -->
    <update id="updateUser" parameterType="USER">
        update user set username=#{userName},address=#{userAddress},sex=#{userAex},birthday=#{userBirthday} where id=#{userId}
    </update>

    <!-- 删除用户-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{uid}
    </delete>
    
    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultMap="userMap">
        select * from user where id = #{uid}
    </select>

    <!-- 根据名称模糊查询 -->
    <select id="findByName" parameterType="string" resultMap="userMap">
          select * from user where username like #{name}
        <!-- select * from user where username like '%${value}%'-->
   </select>

    <!-- 获取用户的总记录条数 -->
    <select id="findTotal" resultType="int">
        select count(id) from user;
    </select>

    <!-- 根据queryVo的条件查询用户 -->
    <select id="findUserByVo" parameterType="home.sise.cn.domain.QueryVo" resultMap="userMap">
        select * from user where username like #{user.username}
    </select>
</mapper>

实体类

public class QueryVo {
    private User user;
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}

小注意:
1.parameterType为参数类型,resultType为返回值类型
2.因为在主配置文件中使用了别名,所以type中可以直接使用user,而且不区分大小写。
3.parameterType如果为8中基本类型,那么占位符#{}中的值可以任意,如果是其他值,则必须对应着实体类来写
4.当实体类和数据库的表没有一一对应时,可以使用在映射文件中给字段起别名或者resultMap
5.resultMap中,column是数据库字段,property是实体类属性,type是返回值类型,id是唯一标识。

mybatis映射文件标签

if,where标签

 <select id="findUserByCondition" resultMap="userMap" parameterType="user">
        select * from user
        <where>
            <if test="userName != null">
                and username = #{userName}
            </if>
            <if test="userSex != null">
                and sex = #{userSex}
            </if>
            <if test="userAddress !=null">
                and address = #{userAddress}
            </if>
        </where>
    </select>

sql,foreach标签
foreach属性:
collection:代表要遍历的集合元素,类似jstl中的items
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,类似jstl中的var
sperator:代表分隔符
相当于sql: select * from user where ids != null and ids.size()>0 and id in (?)

<!-- 了解的内容:抽取重复的sql语句-->
    <sql id="defaultUser">
        select * from user
    </sql>

<select id="findUserInIds" resultMap="userMap" parameterType="queryvo">
        <include refid="defaultUser"></include>
        <where>
            <if test="ids != null and ids.size()>0">
                <foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
                    #{uid}
                </foreach>
            </if>
        </where>
    </select>

小注意
如果引用其它 mapper.xml 的 sql 片段,则在引用时需要加上 namespace,如下:
<include refid="namespace.sql 片段”/>

mybatis表之间关联关系

每个账户所属一个用户 : 一对一

方式一
<!-- 定义封装account和user的resultMap -->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!-- 一对一的关系映射:配置封装user的内容
        select属性指定的内容:查询用户的唯一标识:
        column属性指定的内容:用户根据id查询时,所需要的参数的值
        -->
        <association property="user" column="uid" javaType="user" select="home.sise.cn.dao.IUserDao.findById"></association>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="accountUserMap">
        select * from account
    </select>
    
     <!-- 根据用户id查询账户列表 -->
    <select id="findAccountByUid" resultType="account">
        select * from account where uid = #{uid}
    </select>
    
方式二
<!-- 定义封装account和user的resultMap,其中account用到了别名 -->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></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.uid,a.money from account a , user u where u.id = a.uid;
    </select>

resultMap中id标签是对应表中的主键

一个用户有多个账户 :一对多

 <!-- 定义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>
        <!-- 配置user对象中accounts集合的映射 -->
        <collection property="accounts" ofType="account" select="home.sise.cn.dao.IAccountDao.findAccountByUid" column="id"></collection>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userAccountMap">
        select * from user
    </select>

    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="user">
        select * from user where id = #{id}
    </select>
    
方式二:
<!-- 定义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>
        <!-- 配置user对象中accounts集合的映射 -->
        <collection property="accounts" ofType="account">
            <id column="id" property="id"></id>
            <result column="uid" property="uid"></result>
            <result column="money" property="money"></result>
        </collection>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userAccountMap">
        select * from user u left outer join account a on u.id = a.uid
    </select>

mybatis的缓存

缓存是什么?
存在内存中的临时数据。

为什么使用缓存?
减少和数据库的交互次数,提高了执行效率。

适合用缓存的情况
1.需要经常进行查询,而且不会经常变动的。
2.数据的正确与否对最终的结果影响不大。

不适合用缓存的情况
1.经常改变的数据
2.数据的正确与否对最终的影响很大。
例如:商品的库存,银行的汇率.

默认一级缓存,范围是在一个session中
当我们执行查询之后,查询的结果会同时存入到session为我们提供一块区域中。该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去session中查询是否有,有的话直接拿出来用。当session对象消失时,mybatis的一级缓存也就消失了。
当调用 session 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。

二级缓存,范围是在一个sessionFactory中
二级缓存存放的是数据
使用步骤:
第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)

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

第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
第三步:让当前的操作支持二级缓存(在select标签中配置)

<mapper namespace="home.sise.cn.dao.IUserDao">
    <!--开启user支持二级缓存-->
    <cache/>
    <!-- 根据id查询用户 -->
    <select id="findById" parameterType="INT" resultType="user" useCache="true">
        select * from user where id = #{uid}
    </select>
</mapper>
发布了24 篇原创文章 · 获赞 14 · 访问量 658

猜你喜欢

转载自blog.csdn.net/weixin_44860598/article/details/104700252