Mybatis框架的一点个人心得

MyBatis

mybatis 框架是现在比较流行的一个持久层框架,以下是我自己写的一些总结,主要讲的时它的使用方式,详细资料请访问他们的官网

概述

mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。

mybatis 通过 xml注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。

ORM:
	Object Relational Mappging 对象关系映射
	简单的说:就是把数据库表和实体类及实体类的属性对应起来让我们可以操作实体类就实现操作数据库表。

开发方式

它的使用方法分为两种一种是 xml 配置文件,另一种是直接使用注解。

这两种方式各有优势,其中 xml 配置文件的优势在于思路清晰,维护方便,在需要修改项目时,不需要重新编译,只需要修改配置文件即可;而注解开发,因为不需要去配置文件,所以它的开发速度更快,也是因为这点,近几年来也更流行使用注解开发。

主配置文件的编写,通常命名为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="jdbcConfig.properties"></properties>
	    <!--使用typeAliases配置别名,它只能配置domain中类的别名,批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
	    <typeAliases>
	        <package name="com.itheima.domain"></package>
	    </typeAliases>
		<!-- 配置 mybatis 的环境 -->
		<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>
		<!-- 告知 mybatis 映射配置的位置 -->
		<mappers>
			<package name="com.itheima.dao"></package>
		</mappers>
	</configuration>
  • 在使用 properties 标签配置时,我们可以配置文件来指定属性配置。这样,下面的数据库信息就可以引用配置文件,方便以后修改。
  • 在使用 typeAliases 标签,我们可以也可以采用自定义别名的方式来开发,别名不区分大小写。
  • mappers 标签有两种子标签
    • mapper标签里面有两个常用属性(注意:资源路径之间用/分隔,包路径用.分隔。)
      • mapper 标签里的的 resource 属性使用相对于类路径的资源,使用 xml 开发时才使用。
      • mapper 标签里的的 class 属性使用 mapper 接口类路径,使用注解开发时才使用。(注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。)
    • package 标签里的 name 属性指定包下的所有 mapper 接口,两种开发方式均可使用,也更为常用,它可以用来替代 mapper标签。(注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。)

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.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 id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user;-->
        select * from user;
    </select>
</mapper>
  • 在使用 mapper 标签时,其中的 namespace 属性必须是 dao 类的全限定类名,因为 mabatis 框架是根据 namespace 属性和 statemen 标签中的 id 属性来对数据库进行操作的,也就是根据com.itheima.dao.IUserDao.findAll 反射来确定的。
  • 数据库中表的列名与我们实体类中的成员变量名不一致时,我们可以通过取别名的方式来对结果封装,或者是用 resultMap 标签来指定列名及其对应的变量名,当我们在对查询结果封装需要用到它时,就可以直接使用 resultMap 属性来引用它,如果不需要时,就可以直接使用 resultType 属性来直接指定所要封装的类。
  • 对数据库的四种增删改查操作分别对应 insert delete update select四种标签
根据条件查询时
	<!-- 根据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>
  • 查询的条件使用#{xxx}来作为占位符使用,当只有一个条件时,花括号里的内容可以随便写,当有多个条件时,花括号里的内容就必须与实体类中的变量名相同。
  • 使用模糊查询时的占位符有两种形式#{name}'%${value}%',前者花括号内可以随便写,而后者必须写 value ,但是前者的 % 符号只能在 java 语句中去拼接,而后者就可以在配置文件中写好。
动态sql语句
<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="ids != null and ids.size()>0">
            <foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
                #{uid}
            </foreach>
        </if>
    </where>
</select>
  • where 标签是用来代替 sql 语句中的 where 或者 and 关键字的,它会根据实际情况判断。
  • if 标签是用来判断是否需要用到这个条件时的。
  • foreach 标签就是进行范围查询时使用,其中的 collection 属性对应实体类中的变量名,openclose 属性就是单纯的拼接,item 属性是指定每一个遍历的变量名,separator 属性是指定分隔符。标签体中的内容与就是每一次遍历的占位符,花括号里的内容与 item 属性保持一致。
多表查询

在 mybatis 中只有一对一和一对多,它将多对多当成了多个一对多,而多对一就是多个一对一。

一对一
<!-- 定义封装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.uid,a.money from account a , user u where u.id = a.uid;
</select>
  • 使用 association 标签来指定关联的对应表的单条数据,其中的 property 属性对应实体类中的变量名,column 属性对应关联的外键名称,javaType 指定要封装的实体类。在标签体中,必须先写从表的主键列。
一对多
<!-- 定义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="aid" 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>
  • 使用 collection 标签来指定关联的对应表的多条数据,其中其中的 property 属性对应实体类中的变量名,ofType 指定每一条数据所要封装的实体类。在标签体中,必须先写从表的主键列。
延迟加载和立即加载

延迟加载就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载。在一对多时通常采用延迟加载,而在一对一时通常采用立即加载,因为这样能提高数据库性能。

首先要在主配置文件中开启延迟加载

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

然后在映射文件中进行配置

<!-- 定义封装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>
    <association property="user" column="uid" javaType="user" select="com.itheima.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>

<!-- 定义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="com.itheima.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 = #{uid}
</select>
  • 上面分别是一对一和一对多的延迟加载配置,其实就是在 association 标签或者是 collection 标签中添加 select 属性来指定关联的表需要用到哪个方法来查询,即对应的类的dao接口的全限定名.方法名,以及 column 属性来指定关联的外键名称。可以省去我们在多表查询时编写复杂的 sql 语句。

注解开发方式

在使用注解开发时,不要有映射配置文件的存在,否则程序会以为你要使用 xml 配置文件开发。

基本使用方法
public interface IUserDao {
	@Select("select * from user")
	@Results(id="userMap",value={
        @Result(id=true,column = "id",property = "userId"),
        @Result(column = "username",property = "userName"),
        @Result(column = "address",property = "userAddress"),
        @Result(column = "sex",property = "userSex"),
        @Result(column = "birthday",property = "userBirthday")
		})
  	List<User> findAll();

	@Select("select * from user  where id=#{id} ")
	@ResultMap("userMap")
	User findById(Integer userId);
}
  • 只需要在方法上添加注解,并且在注解中表明 sql 语句即可。对数据库的四种增删改查操作D分别对应 @Insert @delete @Update @Select四种注解。
  • 数据库中表的列名于我们实体类中的成员变量名不一致时,我们可以通过取别名的方式来对结果封装,或者是用 @Results 标签来指定列名及其对应的变量名。当其它的方法在对查询结果封装需要用到它时,就可以直接使用 @ResultMap 注解来引用它。
根据条件查询时
@Select("select * from user  where id=#{id} ")
@ResultMap("userMap")
User findById(Integer userId);

@Select("select * from user where username like #{username} ")
@ResultMap("userMap")
List<User> findUserByName(String username);
  • 查询的条件使用#{xxx}来作为占位符使用,当只有一个条件时,花括号里的内容可以随便写,当有多个条件时,花括号里的内容就必须与实体类中的变量名相同。
  • 使用模糊查询时的占位符只有一种形式 #{name} ,花括号内可以随便写。
动态 sql 语句查询

使用注解进行动态 sql 语句查询时,需要用到上述 xml 开发方式里的动态 sql 语句查询的标签,并且将其置于<script> </script>标签中,将其当作脚本执行,使用起来极其不便,不推荐使用。

多表查询
@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(property = "user",column = "uid",
				one=@Oneselect(select="com.itheima.dao.IUserDao.findById",
							fetchType= FetchType.EAGER))
})
List<Account> findAll();
  • 在一对一查询时,使用 @Result注解来指定关联的对应表的单条数据,其中的 property 属性对应实体类中的变量名,column 属性对应关联的外键名称,然后在注解中使用@One 注解添加 select 属性来指定关联的表需要用到哪个方法来查询,即对应的类的dao接口的全限定名.方法名,以及 fetchType 属性来指定加载方式。

      @Select("select * from user")
      @Results(id="userMap",value={
              @Result(id=true,column = "id",property = "userId"),
              @Result(column = "username",property = "userName"),
              @Result(column = "address",property = "userAddress"),
              @Result(column = "sex",property = "userSex"),
              @Result(column = "birthday",property = "userBirthday"),
              @Result(property = "accounts",column = "id",
                      many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid",
                                  fetchType = FetchType.LAZY))
      })
      List<User> findAll();
    
  • 在一对多查询时,使用 @Result注解来指定关联的对应表的单条数据,其中的 property 属性对应实体类中的变量名,column 属性对应关联的外键名称,然后在注解中使用@Many 注解添加 select 属性来指定关联的表需要用到哪个方法来查询,即对应的类的dao接口的全限定名.方法名,以及 fetchType 属性来指定加载方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值