MyBatis的基本应用

源码地址

01.MyBatis环境搭建

  1. 添加MyBatis的坐标

            <!--mybatis坐标-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.9</version>
            </dependency>
            <!--mysql驱动坐标-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.33</version>
                <scope>runtime</scope>
            </dependency>
            <!--单元测试坐标-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13.2</version>
            </dependency>
    
  2. 创建数据表

  3. 编写DO实体类

  4. 编写映射⽂件UserMapper.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="com.muchfish.dao.IUserDao">
        <!--namespace : 名称空间:与id组成sql的唯一标识
            resultType: 表明返回值类型-->
        
        <!--查询用户-->
        <select id="findAll" resultType="com.muchfish.pojo.User">
            select * from User
        </select>
        
        
    </mapper>
    
  5. 编写核⼼⽂件SqlMapConfig.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文件-->
        <properties resource="jdbc.properties"/>
    
        <!--environments:运行环境-->
        <environments default="development">
            <environment id="development">
                <!--当前事务交由JDBC进行管理-->
                <transactionManager type="JDBC"/>
                <!--当前使用mybatis提供的连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
    
        <!--引入映射配置文件-->
        <mappers>
            <mapper resource="UserMapper.xml"/>
        </mappers>
    
    
    
    </configuration>
    

    jdbc.properties

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql:///mybatis
    jdbc.username=root
    jdbc.password=123456
    
  6. 编写测试类

        @Test
        public void test1() throws IOException {
         
            //1.Resources工具类,配置文件的加载,把配置文件加载成字节输入流
            InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
            //2.解析了配置文件,并创建了sqlSessionFactory工厂
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
            //3.生产sqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();// 默认开启一个事务,但是该事务不会自动提交
            //在进行增删改操作时,要手动提交事务
            //4.sqlSession调用方法:查询所有selectList  查询单个:selectOne 添加:insert  修改:update 删除:delete
            List<User> users = sqlSession.selectList("com.muchfish.dao.IUserDao.findAll");
            for (User user : users) {
         
                System.out.println(user);
            }
            sqlSession.close();
    
        }
    

02.MyBatis的CRUD

  1. CRUD的API

    • sqlSession.selectList()、sqlSession.selectOne()
    • sqlSession.insert()
    • sqlSession.update()
    • sqlSession.delete()
  2. 注意问题

    • 在进行增删改操作时,要手动提交事务。

      sqlSessionFactory.openSession()默认开启一个事务,但是该事务不会自动提交

    • mapper.xml中的Sql语句中使⽤#{任意字符串}⽅式引⽤传递的单个参数

      <!--删除-->
      <delete id="deleteUser" parameterType="int">
          delete from user where id = #{abc}
      </delete>
      
    • sqlSession.close():释放资源

    • sqlSession.commit()

    • sqlSession.rollback()

    • sqlSessionFactory.openSession(true):事务自动提交

03.MyBatis相关配置文件

sqlMapConfig.xml

在这里插入图片描述
在这里插入图片描述

  • mapper标签

    该标签的作⽤是加载映射的,加载⽅式有如下⼏种:

    •使⽤相对于类路径的资源引⽤,例如:
    <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
    
    •使⽤完全限定资源定位符(URL),例如:
    <mapper url="file:///var/mappers/AuthorMapper.xml"/>
    
    •使⽤映射器接⼝实现类的完全限定类名,例如:
    <mapper class="org.mybatis.builder.AuthorMapper"/>
    注意:保证接口名和xml文件名一致且包结构一致(是否包结构一直皆可,文件名可以不一致)
    
    •将包内的映射器接⼝实现全部注册为映射器,例如:
    <package name="org.mybatis.builder"/>
    注意:保证接口名和xml文件名一致且包结构一致。(是否包结构一直皆可,文件名可以不一致。测试得:文件名也必须一致)
    

XXXmapper.xml

在这里插入图片描述

04.MyBatis的Dao层代理开发方式与mappers标签测试

mappers标签测试

•使⽤映射器接⼝实现类的完全限定类名,例如:
<mapper class="com.muchfish.dao.IUserDao"/>
注意:保证接口名和xml文件名一致且包结构一致

•将包内的映射器接⼝实现全部注册为映射器,例如:
<package name="com.muchfish.dao"/>
注意:保证接口名和xml文件名一致且包结构一致。

在这里插入图片描述

Dao层代理开发

Mapper 接⼝开发需要遵循以下规范:

  1. Mapper.xml⽂件中的namespace与mapper接⼝的全限定名相同
  2. Mapper接⼝⽅法名和Mapper.xml中定义的每个statement的id相同
  3. Mapper接⼝⽅法的输⼊参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
  4. Mapper接⼝⽅法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

在这里插入图片描述

05.MyBatis的多对多复杂映射

  1. DO类

    public class User {
         
    
        private Integer id;
        private String username;
        private String password;
        private String birthday;
        //表示用户关联的角色
        private List<Role> roleList = new ArrayList<>();
        
        //。。。省略getter/setter
    }    
    
  2. Mapper.xml

        <resultMap id="userRoleMap" type="com.muchfish.pojo.User">
            <result property="id" column="userid"></result>
            <result property="username" column="username"></result>
            <collection property="roleList" ofType="com.muchfish.pojo.Role">
                <result property="id" column="roleid"></result>
                <result property="roleName" column="roleName"></result>
                <result property="roleDesc" column="roleDesc"></result>
            </collection>
        </resultMap>
    
        <select id="findAllUserAndRole" resultMap="userRoleMap">
            select * from user u left join sys_user_role ur on u.id = ur.userid
                                 left join sys_role r on r.id = ur.roleid
        </select>
    
  3. Dao接口

    public interface IUserDao {
         
    	public List<User> findAllUserAndRole();
    }
    

06.MyBatis的注解开发

  • MyBatis的常⽤注解

    • @Insert:实现新增
    • @Update:实现更新
    • @Delete:实现删除
    • @Select:实现查询
    • @Result:实现结果集封装
    • @Results:可以与@Result ⼀起使⽤,封装多个结果集
    • @One:实现⼀对⼀结果集封装
    • @Many:实现⼀对多结果集封装
  • 注解一对多查询

    public interface IOrderDao {
         
    
    
        //查询订单的同时还查询该订单所属的用户
    
        @Results({
         
                @Result(property = "id",column = "id"),
                @Result(property = "orderTime",column = "orderTime"),
                @Result(property = "total",column = "total"),
                @Result(property = "user",column = "uid",javaType = User.class,
                        one=@One(select = "com.muchfish.dao.IUserDao.findUserById"))
        })
        @Select("select * from orders")
        public List<Order> findOrderAndUser();
    
    
        @Select("select * from orders where uid = #{uid}")
        public List<Order> findOrderByUid(Integer uid);
    
    }
    
    • 注解和xml混合使用命中同一个statementId会报错

07.MyBatis缓存

⼀级缓存

private IUserDao userMapper;
private SqlSession sqlSession;
private SqlSessionFactory sqlSessionFactory;



@Before
public void before() throws IOException {
   
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    sqlSession = sqlSessionFactory.openSession();
    userMapper = sqlSession.getMapper(IUserDao.class);

}

@Test
public void test1() {
   
    //第⼀次查询,发出sql语句,并将查询出来的结果放进缓存中
    User u1 = userMapper.findUserById(1);
    System.out.println(u1);
    //第⼆次查询,由于是同⼀个sqlSession,会在缓存中查询结果
    //如果有,则直接从缓存中取出来,不和数据库进⾏交互
    User u2 = userMapper.findUserById(1);
    System.out.println(u2);
    sqlSession.close();
}

查看控制台打印情况:

在这里插入图片描述

    @Test
    public void test2(){
   
        //根据 sqlSessionFactory 产⽣ session
        //第⼀次查询,发出sql语句,并将查询的结果放⼊缓存中
        User u1 = userMapper.findUserById( 1 );
        System.out.println(u1);
        //第⼆步进⾏了⼀次更新操作, sqlSession.commit()
        u1.setPassword("23131");
        userMapper.updateUserByUserId(u1);
        sqlSession.commit();
        //第⼆次查询,由于是同⼀个sqlSession.commit(),会清空缓存信息
        //则此次查询也会发出sql语句
        User u2 = userMapper.findUserById(1);
        System.out.println(u2);
        sqlSession.close();
    }

查看控制台打印情况:
日志略:第⼆次查询会打印sql语句

在这里插入图片描述

  • 总结
    1. 第⼀次发起查询⽤户id为1的⽤户信息,先去找缓存中是否有id为1的⽤户信息,如果没有,从 数据库查询⽤户信息。得到⽤户信息,将⽤户信息存储到⼀级缓存中。
    2. 如果中间sqlSession去执⾏commit操作(执⾏插⼊、更新、删除),则会清空SqlSession中的 ⼀级缓存,这样做的⽬的为了让缓存中存储的是最新的信息,避免脏读。
    3. 第⼆次发起查询⽤户id为1的⽤户信息,先去找缓存中是否有id为1的⽤户信息,缓存中有,直 接从缓存中获取⽤户信息

二级缓存

在这里插入图片描述

  1. 使用二级缓存

    1. 开启⼆级缓存

      1. 在全局配置⽂件sqlMapConfig.xml⽂件中开启

        <!--开启⼆级缓存 注意<settings>标签的顺序,在<properties>标签后面-->
        <settings>
        <setting name="cacheEnabled" value="true"/>
        </settings>
        
      2. 在Mapper.xml⽂件中开启缓存

            <!--使用二级缓存-->
            <cache></cache>
        
      3. 在DAO接口中开启缓存(可选。使用@CacheNamespace会报错。)

        @CacheNamespace
        public interface IUserDao {
                 
        
        }
        

        @CacheNamespaceRef(IUserDao.class) 
        //@CacheNamespace
        public interface IUserDao {
                 
            
        }
        
        • xml和对应dao接口上同时开启二级缓存会报错,此时只能使用@CacheNamespaceRef
    2. DO序列化

      public class User implements Serializable {
             
      	//。。。
      }
      
    3. 测试

       @Test
          public void SecondLevelCache(){
             
              //根据 sqlSessionFactory 产⽣ session
              SqlSession sqlSession1 = sqlSessionFactory.openSession();
              SqlSession sqlSession2 = sqlSessionFactory.openSession();
              SqlSession sqlSession3 = sqlSessionFactory.openSession();
              String statement = "com.lagou.pojo.UserMapper.selectUserByUserld" ;
              IUserDao userMapper1 = sqlSession1.getMapper(IUserDao. class );
              IUserDao userMapper2 = sqlSession2.getMapper(IUserDao. class );
              IUserDao userMapper3 = sqlSession2.getMapper(IUserDao. class );
              //第⼀次查询,发出sql语句,并将查询的结果放⼊缓存中
              User u1 = userMapper1.findById( 1 );
              System.out.println(u1);
              sqlSession1.close(); //第⼀次查询完后关闭sqlSession
              //执⾏更新操作, commit()。注释掉此处,sqlSession2的查询会走缓存。放开此处,会走数据库
      //        u1.setUsername( "aaa" );
      //        userMapper3.updateUserByUserId(u1);
      //        sqlSession3.commit();
              //第⼆次查询,由于上次更新操作,缓存数据已经清空(防⽌数据脏读),这⾥必须再次发出sql语
              User u2 = userMapper2.findById( 1 );
              System.out.println(u2);
              sqlSession2.close();
      
      
          }
      
  2. useCache和flushCache

    1. useCache:开启或禁用缓存

          <select id="findById" resultType="com.muchfish.pojo.User" useCache="true">
              select * from user where id = #{id}
          </select>
      
    2. flushCache:刷新缓存

          <select id="findById
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸魚散人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值