Mybatis常规使用

Mybatis

一、jdbc初始操作:

​ 1.加载数据库驱动(写死“com.mysql.jdbc.Driver”)
​ 2.通过驱动管理类获取数据库连接
​ 3.定义sql语句,执行
​ 4.释放资源

存在问题:

​ 1.频繁创建数据库连接,释放资源造成系统资源浪费,影响性能;使用连接池可解决
​ 2.Sql语句在代码中写死,实际情况可能会经常改变,不利于维护

二、快速入门:

​ 1.引入jar包/maven坐标
​ 2.编写实体类,编写持久层接口
​ 3.在resource目录下编写持久层接口的映射文件
​ a.必须.xml,层级目录及名字必须相同
​ b.mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名
​ c. 配置文件中的“ #{} ”代表占位符,同“?”;如果参数不是基本类型(对象),#{} 内就要用 #{对象.属性} (ognl 表达式),它会先去找该对象,然后通过其get方法把值取出来,若在 parameterType 属性上指定了实体类名 称,则对象可以省略。

​ 4.编写SqlMapConfig.xml配置文件

	<configuration>
            <!-- 配置 mybatis 的环境 -->
      <environments default="mysql">
            <!-- 配置 mysql 的环境 -->
      <environment id="mysql">
            <!-- 配置事务的类型 -->
         <transactionManager type="JDBC"></transactionManager>
            <!-- 配置连接数据库的信息:用的是数据源(连接池) -->
         <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/ee50"/>
            <property name="username" value="root"/>
            <property name="password" value="1234"/>
         </dataSource>
      </environment>
      </environments>
            <!-- 告知 mybatis 映射配置的位置 -->
      <mappers>
         <mapper resource="com/itheima/dao/IUserDao.xml"/>
      </mappers>
    </configuration>

​ 5.测试步骤
​ a.读取SqlMapConfig.xml【InputStream in = Resource.getResourceAsStream(“SqlMapConfig.xml”);】
​ b.创建SqlSessionFactory构建者对象 【SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();】
​ c.创建SqlSessionFactory工厂对象 【SqlSessionFactory factory = builder.build(in);】
​ d.创建SqlSession对象 【SqlSession sqlSession = factory.openSession();】
​ e.使用SqlSession对象获取dao对象 【Dao dao = sqlSession.getMapper(Dao.class);】
​ f.调用方法,释放资源

三、#{ } 和 ${ } 的区别

​ #{ }:相当于一个占位符;可以自动实现java类型和jdbc类型的转换,可以有效防止sql注入问题;若parameterType 传递简单类型值, #{ } 中的值可以任意。
: 可 以 将 p a r a m e t e r T y p e 传 入 的 值 和 s q l 语 句 进 行 拼 接 , 不 实 现 j a v a 类 型 和 j d b c 类 型 的 转 换 ; 如 果 p a r a m e t e r T y p e 传 输 单 个 简 单 类 型 值 , { }:可以将parameterType传入的值和sql语句进行拼接,不实现java类型和jdbc类型的转换;如果 parameterType 传输单个简单类型值, parameterTypesqljavajdbcparameterType{}括号中只能是 value。

四、传递pojo包装对象(即pojo中包含pojo)

​ 1.编写QueryVo(内涵一个User对象)
​ 2.编写持久层接口
​ 3.编写持久层映射文件
​ <select id=“findByVo” resultType=“com.itheima.domain.User”
​ parameterType=“com.itheima.domain.QueryVo”>
​ select * from user where username like #{user.username};

五、Mybatis的结果集封装

注意: resultType它和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用 全限定类名。同时,当是实体类名称是,还有一个要求,实体类中的属性名称必须和查询语句中的列名保持 一致,否则无法实现封装。

解决查询列名和实体类属性名不一致方法:

​ 1.sql语句中给列名起别名
​ 2.用resultMap建立列名和属性名的对应关系

            <resultMap type="com.itheima.domain.User" id="userMap">  (id唯一标识该resultMap)
                <id column="id" property="userId"/>					(id标签:指定主键字段)
                <result column="username" property="userName"/>		 (column:列名)
                <result column="sex" property="userSex"/>			 (property:属性名)
                <result column="address" property="userAddress"/>	  (result标签:指定非主键字段)
                <result column="birthday" property="userBirthday"/>
            </resultMap>

六、SqlMapConfig.xml常用标签

1.-properties(属性) --property

​ 第一种:

       <properties>
          <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
          <property name="jdbc.url" value="jdbc:mysql://localhost:3306/eesy"/>
          ......
       </properties>

​ 第二种:(加载配置文件)

        <properties 
        	url = file:///D:/IdeaProjects/day02_eesy_01mybatisCRUD/src/main/resources/jdbcConfig.prop
        	erties">
        </properties>
        <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>
2.-typeAliases(类型别名) --typeAliase --package
    在 SqlMapConfig.xml 中配置:
    <typeAliases>
   	 	<!-- 单个别名定义 -->
    	<typeAlias alias="user" type="com.itheima.domain.User"/>
    	<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
    	<package name="com.itheima.domain"/>
    	<package name="其它包"/>
    </typeAliases>
3.-mappers(映射器) --mapper --package
    1.使用相对于类路径的资源
    	如:<mapper resource="com/itheima/dao/IUserDao.xml" />
    2.使用 mapper 接口类路径
    	如:<mapper class="com.itheima.dao.UserDao"/>
    	注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。 
    3.注册指定包下的所有 mapper 接口
    	如:<package name="com.itheima.dao"/>
    	注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。 
映射文件中会有<mapper namespace="com.itheima.dao.IUserDao">各类sql语句</mapper>与之建立联系

七、Mybatis中数据源(连接池)的配置

​ 1.type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
​ 2.type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
​ 3.type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
​ **注意:**Mybatis是通过工厂模式创建数据源DataSource对象的,其内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSource, PooledDataSource 类来表示 UNPOOLED、POOLED 类型的数据源

八、Mybatis中的事务控制

​ Mybatis中的事务提交本质上就是调用JDBC的serAutoCommit()方法来实现事务控制。但是在进行CUD操作过程 中需要我们手动进行事务提交,原因是Mybatis自动默认setAutoCommit()方法值为false。可以在创建session对象时 factory.openSession(true)来使其自动提交。不过还是使用默认false再视情况考虑事务的提交【session.commit()】。

九、Mybatis中动态sql语句

1.sql语句的省略
	<sql id = "defaultSql">
		select * from user
	</sql>
	此后在select标签中加入
		<include refid="defaultSql"></include>
	即可省略相同语句的写入
2. i f 标签:
    <select id="findByUser" resultType="user" parameterType="user">
    	select * from user where 1=1
    	<if test="username!=null and username != '' ">
    		and username like #{username}
    	</if>
    	<if test="address != null">
    		and address like #{address}
   	 	</if>
    </select>
    注意:<if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。
    另外要注意 where 1=1 的作用~!
3. where 标签:
    <select id="findByUser" resultType="user" parameterType="user">
    	select * from user
    	<where>
    		<if test="username!=null and username != '' ">
    			and username like #{username}
    		</if>
    		<if test="address != null">
    			and address like #{address}
    		</if>
    	</where>
    </select>
4. foreach 标签:
    <!-- 查询所有用户在 id 的集合之中,queryvo中含有集合ids属性 -->
    <select id="findInIds" resultType="user" parameterType="queryvo">
    <!-- select * from user where id in (1,2,3,4,5); -->
    	<include refid="defaultSql"></include>
    	<where>
    		<if test="ids != null and ids.size() > 0">
    			<foreach collection="ids" open="id in ( " close=")" item="uid"
    			separator=",">
    				#{uid}
    			</foreach>
   	 		</if>
    	</where>
    </select>
    SQL 语句:
    select 字段 from user where id in (?)
    <foreach>标签用于遍历集合,它的属性:
    collection:代表要遍历的集合元素,注意编写时不要写#{}
    open:代表语句的开始部分
    close:代表结束部分
    item:代表遍历集合的每个元素,生成的变量名
    sperator:代表分隔符

十、Mybatis中的多表查询

1.一对一(多对一):
方式一:

​ 创建一个查询结果字段都有的实体类,编写映射文件

    <?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.IAccountDao">
    <!-- 配置查询所有操作-->
    	<select id="findAll" resultType="accountuser">
    		select a.*,u.username,u.address from account a,user u where a.uid =u.id;
    	</select>
    </mapper>
    注意:因为上面查询的结果中包含了账户信息同时还包含了用户信息,所以我们的返回值类型 returnType
    的值设置为 AccountUser 类型,这样就可以接收账户信息和用户信息了。
方式二:

​ 在多的类中加入一的类,在映射文件中使用resultMap对主表和从表进行一一对应关系

    <?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.IAccountDao">
    	<!-- 建立对应关系 -->
    	<resultMap type="account" id="accountMap">
    		<id column="aid" property="id"/>
    		<result column="uid" property="uid"/>
    		<result column="money" property="money"/>
    		<!-- 它是用于指定从表方的引用实体属性的 -->
    		<association property="user" javaType="user">
    			<id column="id" property="id"/>
    			<result column="username" property="username"/>
    			<result column="sex" property="sex"/>
    			<result column="birthday" property="birthday"/>
    			<result column="address" property="address"/>
    		</association>
    	</resultMap>
    	<select id="findAll" resultMap="accountMap">
    		select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
    	</select>
    </mapper>
2.一对多查询:

​ 在一的类中加入多的类的集合,通过resultMap对两个类中的属性和数据库列名进行一一对应

    <resultMap type="user" id="userMap">
    	<id column="id" property="id"></id>
    	<result column="username" property="username"/>
    	<result column="address" property="address"/>
    	<result column="sex" property="sex"/>
    	<result column="birthday" property="birthday"/>
    	<!-- collection 是用于建立一对多中集合属性的对应关系
    		ofType 用于指定集合元素的数据类型-->
    	<collection property="accounts" ofType="account">
    		<id column="aid" property="id"/>
    		<result column="uid" property="uid"/>
    		<result column="money" property="money"/>
    	</collection>
    </resultMap>
    <!-- 配置查询所有操作 -->
    <select id="findAll" resultMap="userMap">
    	select u.*,a.id as aid ,a.uid,a.money from user u left outer join account a on u.id =a.uid
    </select>
    
    collection
    部分定义了用户关联的账户信息。表示关联查询结果集
    property="accounts":
    关联查询的结果集存储在 User 对象的上哪个属性。
    ofType="account":
    指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名.
3.多对多查询:

​ 需要在两彪之间有一个中间表和中间实体类,中间实体类含有两个类的集合;然后通过resultMap对两个类中的属性 和数据库列名进行一一对应(即同一对多的操作)

     <resultMap id="roleMap" type="role">
     	<id property="roleId" column="rid"></id>
     	<result property="roleName" column="role_name"></result>
     	<result property="roleDesc" column="role_desc"></result>
     	<collection property="users" ofType="user">
     		<id column="id" property="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>
     	</collection>
     </resultMap>
     <!--查询所有-->
     <select id="findAll" resultMap="roleMap">
     	select u.*,r.id as rid,r.role_name,r.role_desc from role r
     	inner join user_role ur on r.id = ur.rid
     	inner join user u on u.id = ur.uid
     </select>
     
INNER JOIN 内连接 :
内连接就是关联的两张或多张表中,根据关联条件,显示所有匹配的记录,匹配不上的,不显示。 

十一、Mybatis的延迟加载

1.延迟加载:

​ 含义:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
​ 好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张 表速 度要快。
​ 坏处:因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗 时间,所以可能造成用户等待时间变长,造成用户体验下降。

2.使用 assocation 实现延迟加载:
<resultMap type="account" id="accountMap">
	<id column="aid" property="id"/>
	<result column="uid" property="uid"/>
	<result column="money" property="money"/>
	<!-- 它是用于指定从表方的引用实体属性的 -->
	<association property="user" javaType="user"
		select="com.itheima.dao.IUserDao.findById" column="uid">
	</association>
</resultMap>
<select id="findAll" resultMap="accountMap">
	select * from account
</select>

select: 填写我们要调用的 select 映射的 id
column : 填写我们要传递给 select 映射的参数

​ 在 IUserdDao.xml 和 IUserdDao 中编写方法

    <!-- 根据 id 查询 -->
    <select id="findById" resultType="user" parameterType="int" >
    	select * from user where id = #{uid}
    </select>
3.使用 Collection 实现延迟加载
<resultMap type="user" id="userMap">
	<id column="id" property="id"></id>
	<result column="username" property="username"/>
	<result column="address" property="address"/>
	<result column="sex" property="sex"/>
	<result column="birthday" property="birthday"/>
	<collection property="accounts" ofType="account"
		select="com.itheima.dao.IAccountDao.findByUid" column="id">
	</collection>
</resultMap>
<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
	select * from user
</select>

<collection>标签:
主要用于加载关联的集合对象
select 属性:
用于指定查询 account 列表的 sql 语句,所以填写的是该 sql 映射的 id
column 属性:
用于指定 select 属性的 sql 语句的参数来源,上面的参数来自于 user 的 id 列,所以就写成 id 这一个字段名了

​ 在 IAccountDao.xml 和 IAccountDao 中编写方法

<select id="findByUid" resultType="account" parameterType="int">
	select * from account where uid = #{uid}
</select>

​ **注意:**上面两种方式都需要在SqlMapConfig.xml中配置开启延迟加载:

<settings>
	<setting name="lazyLoadingEnabled" value="true"/>
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>

十二、Mybatis的缓存:

1.一级缓存:

​ 含义:一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法 时,就会清空sqlSession的缓存
​ 过程:第一次发起查询操作时,先去找缓存中有该信息,如果没有,从数据库查询信息。 得到信息,将信息存储 到一级缓存中。 如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),就会清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

2.二级缓存:

​ 含义:二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。
​ 过程:首先开启mybatis的二级缓存
​ 当第一个sqlSession执行查询,查询到的信息会存储到二级缓存中
​ 之后的sqlSession执行相同mapper映射下的sql时,首先会从缓存中查询是否有数据,有则直接取出
​ 若之后的sqlSession执行相同mapper映射下sql,执行commit,将会清空该mapper映射下的二级缓存数据
​ 二级缓存的开启:
​ 第一步:在SqlMapConfig中配置:

    <settings>
    	<!-- 开启二级缓存的支持 -->
    	<setting name="cacheEnabled" value="true"/>
    </settings>
    
    因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为
    false 代表不开启二级缓存。

​ 第二步:配置相关mapper映射文件

    <?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">
    	<!-- 开启二级缓存的支持 -->
    	<cache></cache>
    </mapper>

    <cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值。

​ 第三步:配置 statement 上面的 useCache 属性

    <select id="findById" resultType="user" parameterType="int" useCache="true">
    	select * from user where id = #{uid}
    </select>
    
    将 UserDao.xml 映射文件中的<select>标签中设置 useCache=”true”代表当前这个 statement 要使用
    二级缓存,如果不使用二级缓存可以设置为 false。
    注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。

十三、Mybatis的常用注解

1.@Results 注解 :

​ 代替的是 标签

    @Results(id="userMap",
    	value= {
            @Result(id=true,column="id",property="userId"),
            @Result(column="username",property="userName"),
            @Result(column="sex",property="userSex"),
            @Result(column="address",property="userAddress"),
            @Result(column="birthday",property="userBirthday")
    })
2.@One 注解(一对一):

​ 代替的是 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
​ 属性介绍: select 指定用来多表查询的 sqlmapper
​ fetchType 会覆盖全局的配置参数lazyLoadingEnabled
​ 使用格式: @Result(column=" “,property=”",one=@One(select=""))

    @Select("select * from account")
    @Results(id="accountMap",
        value= {
            @Result(id=true,column="id",property="id"),
            @Result(column="uid",property="uid"),
            @Result(column="money",property="money"),
            @Result(column="uid",
            property="user",
            one=@One(select="com.itheima.dao.IUserDao.findById",
            fetchType=FetchType.LAZY))
    })
3.@Many注解(一对多):

​ 代替的是 标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
​ **注意:**聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType (一般为 ArrayList)但是注解中可以不定义。

    @Results(id="userMap",
        value= {
            @Result(id=true,column="id",property="userId"),
            @Result(column="username",property="userName"),
            @Result(column="sex",property="userSex"),
            @Result(column="address",property="userAddress"),
            @Result(column="birthday",property="userBirthday"),
            @Result(column="id",property="accounts",
            many=@Many(
            select="com.itheima.dao.IAccountDao.findByUid",
            fetchType=FetchType.LAZY))
    })
4.开启二级缓存:

​ 首先还是要在SqlMapConfig.xml中配置开启二级缓存支持;
​ 然后在持久层类上加@CacheNamespace(blocking=true)

    @CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
    public interface IUserDao {}

Sex"),
@Result(column=“address”,property=“userAddress”),
@Result(column=“birthday”,property=“userBirthday”),
@Result(column=“id”,property=“accounts”,
many=@Many(
select=“com.itheima.dao.IAccountDao.findByUid”,
fetchType=FetchType.LAZY))
})


#### 		4.开启二级缓存:

​			首先还是要在SqlMapConfig.xml中配置开启二级缓存支持;
​			然后在持久层类上加@CacheNamespace(blocking=true)

@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
public interface IUserDao {}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值