Mybatis(二)

1 多对一关联查询

需求:查询某个员工时查询他所在的部门

1.1准备工作

   1.加入部门表t_dept:

 2. 改造员工表,给员工表t_employee添加外键字段d_id

 3.插入测试数据

 4.在domain包中加入Dept类,改造Employee类(加入Dept属性)

1.2使用resultType映射查询结果集(理解)

     由于sql语句是多表的连接查询,结果集中的部门的2个字段不能直接封装到Employee对象上,resultType=”employee”不可用,如果你非要用resultType,则

需要用VO思想对Employee类进行扩展

1.2.1创建EmployeeVo类

EmployeeVo类中扩展部门相关的属性

public class EmployeeVo extends Employee {
	//部门相关的属性
    private Integer did;
    private String dname;

1.2.2创建EmployeeMapper接口

1.2.3 配置EmployeeMapper.xml

1.2.4测试

1.3使用resultMap映射查询结果集(掌握)

多对一或一对一都使用association标签映射关联对象,有两种做法:

1.3.1 使用resultMap结果嵌套

 

配置EmployeeMapper.xml,将关联对象的查询结果嵌套在resultMap中,步骤如下:

  1. A.定义resultMap
 <resultMap type="employee" id="empMap">
        <id column="eid" property="eid"/>
        <result  column="ename"  property="ename"/>
        <result  column="salary"  property="salary"/>
         <!-- association映射关联的对象,javaType不可省略 -->
        <association property="dept"  javaType="Dept">
              <id column="did" property="did"/>
              <result column="dname"  property="dname"/>
        </association>
   </resultMap>
  1. B.引用resultMap
  <select id="queryEmp"  resultMap="empMap">
  select t1.eid,t1.ename,t1.salary,t2.did,t2.dname  from  t_employee  t1 JOIN  t_dept  t2  on t1.d_id=t2.did
    where t1.eid=#{id}
  </select>

1.3.2使用resultMap查询嵌套

查询嵌套即在association中使用select嵌套一个sql查询,将整个查询分成了2步,又叫分步查询.步骤如下:

  1. A.定义resultMap

  <resultMap type="employee" id="empStepMap">
        <id column="eid" property="eid"/>
        <result  column="ename"  property="ename"/>
        <result  column="sex"  property="sex"/>
        <result  column="salary"  property="salary"/>
         <!-- association映射关联的对象 ,column:指定将哪个列的值传给查询方法
          select:指定一个satement的唯一标识,定位查询方法 -->
        <association property="dept"  javaType="dept"  select="cn.sxt.mapper.DeptMapper.queryDept" column="d_id">
        </association>

  </resultMap>

其中associationselect的值引用DeptMapper.xml中的一个select

  1. B.引用resultMap

 <select id="queryEmpPlus"  resultMap="empStepMap">

  select *  from  t_employee

    where eid=#{id}

  </select>

1.3.3测试

2 一对多关联查询

 需求:查询某个部门时查询该部门的所有员工

2.1准备工作

1)改造Dept类,加入一个List集合(Set也可)

  1. .在DeptMapper接口中添加一个方法

2.2使用resultMap映射查询结果集(掌握)

2.2.1 使用resultMap结果嵌套

 

 对 DeptMapper.xml中进行配置,步骤如下:

  1. A.定义resultMap

resultMap中使用collection标签映射关联的集合

<resultMap type="dept" id="deptMap">
		<id column="did" property="did" />
		<result column="dname" property="dname" />
		<!-- collection:映射集合类型的属性  ofType:指定集合中元素的类型  javaType:集合类型(可以省略)  -->
		<collection property="emps" ofType="employee" javaType="list">
			<id column="eid" property="eid" />
			<result column="ename" property="ename" />
			<result column="salary" property="salary" />
		</collection>
	</resultMap>

 

  1. B.引用resultMap

<select id="queryDeptPlus" resultMap="deptMap">

select d.did,d.dname ,

e.eid,e.ename,e.salary from t_dept d LEFT JOIN

t_employee e on

d.did=e.d_id where d.did=#{id}

</select>

2.2.2 使用resultMap查询嵌套

 类似于多对一查询嵌套,又叫分步查询。步骤如下:

  1. A.定义resultMap
<resultMap type="dept" id="deptStepMap">
		     <id  column="did"  property="did"/>
		     <result column="dname" property="dname"/> 
		      <!-- select:指定一个satement的唯一标识,定位查询方法  -->
		     <collection property="emps" ofType="employee"  select="cn.sxt.mapper.EmployeeMapper.queryEmpsByDeptId" column="did"></collection>    
		</resultMap>

其中collection select的值引用EmployeeMapper.xml中的一个select

 

<select id="queryEmpsByDeptId"  resultType="employee">
  select eid,ename,salary,sex from t_employee where d_id=#{id}
  </select>
  1. B.引用resultMap

<select id="queryDeptByStep" resultMap="deptStepMap">

  select * from t_dept where  did=#{id}

</select>

 

2.2.3测试

3 resultType和resultMap总结

resultType: 如果查询的结果集只需要封装为一个对象 (没有级联查其关联对象或集合),使用resultType

resultMap: 如果查询的结果集中包含主对象还要包含其关联的对象时,必须用resultMap来映射结果集;如果表的字段和属性名不一致,也要用resultMap.

4 懒加载(延迟加载)

使用resultMap分步查询时,默认在查询Employee时,将部门对象也一起查出来了。我们希望部门信息在需要用的时候才去查询,此时可以使用延迟加载策略

5.1开启懒加载

在主配置文件的settings标签中,配置如下:

<settings>
	   <!-- true:启用延迟加载 -->
	  <setting name="lazyLoadingEnabled" value="true"/>
	  <!-- false:每种属性将会按需要加载 -->
	  <setting name="aggressiveLazyLoading" value="false"/>
	</settings>

 

5.2测试

5 动态sql

如果你有使用 JDBC 或其他相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么的痛苦,确保不能忘了空格或在列表的最后省略逗号。动态 SQL 可以彻底处理这种痛苦。

通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语 言来改进这种情形,这种语言可以被用在任意映射的 SQL 语句中。

 

          

6.1 if标签

  类似于jsp里的c:if标签

 

select *  from t_employee where 
       <if test="eid!=null">
           eid=#{eid}  
       </if>
       <if test="ename!=null">
           and ename li

 

6.2 where标签

   使用where将所有查询条件包含在内,mybatis会将拼接后SQL的首个and去掉

	select * from t_employee
		<where>
			<if test="eid!=null">
				and eid=#{eid}
			</if>
			<if test="ename!=null">
				and ename like #{ename}
			</if>
			<if test="sex!=null">
				and sex= #{sex}
			</if>
		</where>

6.3 choose标签

有些时候,我们不想用到所有的条件语句,而只想从中选择一个。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 s例如:

select * from t_employeewitch 语句。

		<where>
		   <choose>
		      <when test="eid!=null">
				and eid=#{eid}
			</when>
			<when test="ename!=null">
				and ename like #{ename}
			</when>
			 <otherwise>
			    and sex=#{sex}
			 </otherwise>
		   </choose>	
		</where>

 

如果用户提供了eid就按eid查,  提供了ename值就按ename查,否则就走otherwise

6.4 set标签

使用set标签引出修改的条件,会智能的去掉多余的逗号

 <update id="updateEmp">
	   update t_employee
	   <set>
	     <if test="ename!=null">ename=#{ename},</if>
	      <if test="sex!=null">sex=#{sex}</if>
	   </set>
	   where eid=#{eid}
 </update>

6.5 foreach标签

foreach 元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。

<select id="queryEmps" resultType="employee">	
<!-- 
  collection:指定要遍历的集合(数组),值为array表示传过来的参数是数组,值为list表示参数是List集合类型
	 		item:将当前遍历出的元素赋值给某个变量
	 		separator:每个元素之间的分隔符
	 		open:遍历出所有结果拼接一个开始的字符
	 		close:遍历出所有结果拼接一个结束的字符
	 -->
	  select * from t_employee where eid in
	     <foreach collection="list" item="item_id"  separator="," open="(" close=")">
	            #{item_id}
	     </foreach>    
	</select>

7 mybatis的一二级缓存(了解)

7.1mybatis一级缓存

在SqlSession范围内。当查询相同对象时,会使用缓存中的数据,而不会再次查询。

Mybatis默认开启了一级缓存

7.2mybatis二级缓存

mybatis中的二级缓存是mapper级别的缓存,值得注意的是,不同的mapper通常情况下有不同的namespace,就都有一个二级缓存,也就是说,不同的mapper之间的二级缓存是互不影响的。为了更加清楚的描述二级缓存,先来看一个示意图:

从图中可以看出:

 

1) sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询到的数据存储到该UserMapper的二级缓存中。

2) 如果SqlSession3去执行相同 mapper下sql,执行commit提交,则会清空该UserMapper下二级缓存区域的数据。

3) sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

二级缓存与一级缓存区别在于二级缓存的范围更大,多个sqlSession可以共享一个mapper中的二级缓存区域。mybatis是如何区分不同mapper的二级缓存区域呢?它是按照不同mapper有不同的namespace来区分的

在使用二级缓存之前,首先得开启二级缓存的开关,方法是在主配置文件的settings中加入:

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

然后在你要缓存数据的Mapper.xml中加入一个cache:

注意:需要缓存数据的实体类要实现可序列化接口

 

8 注解

  Mybatis允许我们在mapper.xml中去映射每个Mapper接口的方法,也允许直接在

Mapper接口方法上使用相应的注解来取代XML配置。常用注解:

1).@Insert: 对应的是Mapper.xml中的insert标签

2).@Update

3).@Delete

4).@Select:对应select标签

5).@Param:指定参数的名称

@Param注解用于指定传给占位符的参数名字,此时占位符里面的xxx就必须与注解的参数名一致。通常用在方法的形参前,给该参数指定名字

   注解不能完全代替XML配置的,如果查询结果需要使用resultMap来映射,那么不要用注解,如果要执行动态SQL,也不能用注解。Mybatis允许注解和Mapper.xml配置共存,只要你愿意用。

9 逆向工程

9.1什么是逆向工程

MyBatis的一个主要的特点就是需要程序员自己编写sql,那么如果表太多的话,难免会很麻烦,所以mybatis官方提供了一个逆向工程,可以针对单表自动生成mybatis执行所需要的代码(包括mapper.xml、mapper.java、po..)。一般在开发中,常用的逆向工程方式是数据库的表生成JAVA代码。 (powerDesigner工具快速生成数据表)

9.2 使用逆向工程

使用MyBatis的逆向工程,需要导入逆向工程的jar包,我用的是mybatis-generator-core-1.3.2.jar,下面说一下MyBatis逆向工程的使用步骤

  1. .新建一个java工程

这个工程专门用来使用逆向工程生成代码的。有些人可能会问,为什么要新建一个工程呢?直接在原来工程中你想生成不就可以了么?确实是这样,可以在原来的工程中生成,但是有风险,因为MyBatis是根据配置文件来生成的(下面会说到),如果生成的路径中有相同的文件,那么就会覆盖原来的文件,这样会有风险。所以开发中一般都会新建一个java工程来生成,然后将生成的文件拷贝到自己的工程中,这也不麻烦,而且很安全。加入mybatis-generator-core-1.3.2.jar,mybatis-3.2.8.jar,驱动包

  1. .配置逆向工程的配置文件

  打开mybatis-generator-core-1.3.2目录下的docs里的index.html,里面有模板。

我们用带了中文注释的配置文件generatorConfig.xml,放到项目根路径下。

配置文件主要做的几件事是:

a,连接数据库,这是必须的,要不然怎么根据数据库的表生成代码呢?

要根据实际情况去改模板里的连接数据库的参数

b,指定要生成代码的位置,要生成的代码包括po类,mapper.xml和mapper.java

 

c,指定要对哪些表逆向生成相应的java代码(po类,Mapper接口及Mapper.xml)

3.运行逆向工程生成java代码

执行以下程序即可生成代码了,生成的java程序,下载的逆向工程文档中都有示例,如下:

public class GeneratorSqlmap {

public void generator() throws Exception {

 

List<String> warnings = new ArrayList<String>();

boolean overwrite = true;

// 指定逆向工程配置文件

File configFile = new File("generatorConfig.xml");

ConfigurationParser cp = new ConfigurationParser(warnings);

Configuration config = cp.parseConfiguration(configFile);

DefaultShellCallback callback = new DefaultShellCallback(overwrite);

MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,

callback, warnings);

myBatisGenerator.generate(null);

}

public static void main(String[] args) throws Exception {

try {

GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();

generatorSqlmap.generator();

} catch (Exception e) {

e.printStackTrace();

}

}

}

 

运行完了后刷新一下工程,就可以看到最新生成的代码了。

到这里就生成好了,下面我们就把生成的代码拷贝到自己的工程使用了。 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值