mybatis(二):动态sql、关联查询

本文详细介绍了Mybatis中的动态SQL,包括If、Where和Foreach的使用,展示了如何处理多个ID的查询。此外,还探讨了Sql片段的提取和重用,以及如何进行一对一关联查询,分别通过resultType和resultMap两种方式实现。最后,讨论了Mybatis与Spring的整合,讲解了不同类型的Dao开发方式,强调了SqlSessionFactory在Spring容器中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

输入映射和输出映射

​​​​​​parameterType(输入类型)

resultType(输出类型)

resultMap

resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

<select id="selectByExample" resultMap="BaseResultMap" parameterType="com.it.pojo.TbItemExample" >
	select
	<if test="distinct" >
	  distinct
	</if>
	<include refid="Base_Column_List" />
	from tb_item
	<if test="_parameter != null" >
	  <include refid="Example_Where_Clause" />
	</if>
	<if test="orderByClause != null" >
	  order by ${orderByClause}
	</if>
</select>
<resultMap id="BaseResultMap" type="com.it.pojo.TbItem" >
	<id column="id" property="id" jdbcType="BIGINT" />
	<result column="title" property="title" jdbcType="VARCHAR" />
	<result column="sell_point" property="sellPoint" jdbcType="VARCHAR" />
	<result column="price" property="price" jdbcType="BIGINT" />
	<result column="num" property="num" jdbcType="INTEGER" />
	<result column="barcode" property="barcode" jdbcType="VARCHAR" />
	<result column="image" property="image" jdbcType="VARCHAR" />
	<result column="cid" property="cid" jdbcType="BIGINT" />
	<result column="status" property="status" jdbcType="TINYINT" />
	<result column="created" property="created" jdbcType="TIMESTAMP" />
	<result column="updated" property="updated" jdbcType="TIMESTAMP" />
</resultMap>

动态sql

If & Where

<select id="findUserList" parameterType="user" resultType="user">
	select * from user 
	<where>
		<if test="id!=null and id!=''">
			and id=#{id}
		</if>
		<if test="username!=null and username!=''">
			and username like '%${username}%'
		</if>
	</where>
</select>

foreach

传入多个id查询用户信息,用下边两个sql实现:

SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)

SELECT * FROM USERS WHERE username LIKE '%张%'  AND id IN (10,89,16)

在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法

<!-- mapper.xml -->
<if test="ids!=null and ids.size>0">
	<foreach collection="ids" open=" and id in(" close=")" item="id" separator="," >
		#{id}
	</foreach>
</if>

Sql片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的,如下:

<!-- 传递pojo综合查询用户信息 -->
<select id="findUserList" parameterType="user" resultType="user">
	select * from user 
	<where>
		<if test="id!=null and id!=''">
			and id=#{id}
		</if>
		<if test="username!=null and username!=''">
			and username like '%${username}%'
		</if>
	</where>
</select>

将where条件抽取出来:

<sql id="query_user_where">
	<if test="id!=null and id!=''">
		and id=#{id}
	</if>
	<if test="username!=null and username!=''">
		and username like '%${username}%'
	</if>
</sql>

使用include引用:

<select id="findUserList" parameterType="user" resultType="user">
	select * from user 
	<where>
		<include refid="query_user_where"/>
	</where>
</select>

注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:

<include refid="namespace.sql片段”/>


关联查询

一对一查询:查询所有订单信息,关联查询下单用户信息。

方法一:使用resultType,定义订单信息po类,此po类中包括了订单信息和用户信息:

//java pojo类
public class OrdersCustom extends Orders {
	private String username;// 用户名称
	private String address;// 用户地址
//getter & setter
}

Mapper.xml

<!-- 查询所有订单信息 -->
<select id="findOrdersList" resultType="cn.itcast.mybatis.po.OrdersCustom">
	SELECT
		orders.*,
		user.username,
		user.address
	FROM
		orders,	user
	WHERE 
		orders.user_id = user.id 
</select>

方法二:使用resultMap,定义专门的resultMap用于映射一对一查询结果。

 

在Orders类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。

Mapper.xml

<!-- 查询订单关联用户信息使用resultmap -->
<resultMap type="com.it.po.Orders" id="orderUserResultMap">
	<id column="id" property="id"/>
	<result column="user_id" property="userId"/>
	<result column="number" property="number"/>
	<result column="createtime" property="createtime"/>
	<result column="note" property="note"/>
	<!-- 一对一关联映射 -->
	<!-- 
		property:Orders对象的user属性
		javaType:user属性对应 的类型
	 -->
	<association property="user" javaType="com.it.po.User">
		<!-- column:user表的主键对应的列  property:user对象中id属性-->
		<id column="user_id" property="id"/>
		<result column="username" property="username"/>
		<result column="address" property="address"/>
	</association>
</resultMap>
<select id="findOrdersWithUserResultMap" resultMap="orderUserResultMap">
	SELECT
		o.id,
		o.user_id,
		o.number,
		o.createtime,
		o.note,
		u.username,
		u.address
	FROM
		orders o
	JOIN `user` u ON u.id = o.user_id
</select>

association表示进行关联查询单条记录

property表示关联查询的结果存储在com.it.mybatis.po.Orders的user属性中

javaType表示关联查询的结果类型

<id property="id" column="user_id"/>查询结果的user_id列对应关联对象的id属性,这里是<id />表示user_id是关联查询对象的唯一标识。

<result property="username" column="username"/>查询结果的username列对应关联对象的username属性。

Mybatis整合spring

  1. SqlSessionFactory对象应该放到spring容器中作为单例存在。
  2. 传统dao的开发方式中,应该从spring容器中获得sqlsession对象。
  3. Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。
  4. 数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

	<!-- 加载配置文件 -->
	<context:property-placeholder location="classpath:db.properties" />
	<!-- 数据库连接池 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<property name="maxActive" value="10" />
		<property name="maxIdle" value="5" />
	</bean>
	<!-- mapper配置 -->
	<!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 数据库连接池 -->
		<property name="dataSource" ref="dataSource" />
		<!-- 加载mybatis的全局配置文件 -->
		<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
	</bean>
</beans>

Dao的开发

三种dao的实现方式:

1、传统dao的开发方式

2、使用mapper代理形式开发方式

3、使用扫描包配置mapper代理。

1.传统dao的开发方式

接口+实现类来完成。需要dao实现类需要继承SqlsessionDaoSupport类

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
	@Override
	public User findUserById(int id) throws Exception {
		SqlSession session = getSqlSession();
		User user = session.selectOne("test.findUserById", id);
		//不能关闭SqlSession,让spring容器来完成
		//session.close();
		return user;
	}

	@Override
	public void insertUser(User user) throws Exception {
		SqlSession session = getSqlSession();
		session.insert("test.insertUser", user);
		session.commit();
		//session.close();
	}
}

把dao实现类配置到spring容器中

<!-- 配置UserDao实现类 -->
<bean id="userDao" class="cn.itcast.dao.UserDaoImpl">
	<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

 

2.Mapper代理形式开发dao

<!-- 配置mapper代理对象 -->
<bean class="org.mybatis.spring.mapper.MapperFactoryBean">
	<property name="mapperInterface" value="com.it.mybatis.mapper.UserMapper"/>
	<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

3.扫描包形式配置mapper

<!-- 使用扫描包的形式来创建mapper代理对象 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="com.it.mybatis.mapper"></property>
</bean>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值