Mybatis关联映射和Mapper动态SQL机制

一对一映射

在这里插入图片描述
PersonMapper.xml文件内容为一对一关系
在这里插入图片描述

card.java

package org.fkit.domain;

import java.io.Serializable;

public class Card implements Serializable {
	
	private Integer id;  // 主键id
	private String code; // 身份证编号
	省略getter和setter
}

person.java

public class Person implements Serializable {

	private Integer id;  // 主键id
	private String name; // 姓名
	private String sex;  // 性别
	private Integer age; // 年龄
	
	// 人和身份证是一对一的关系,即一个人只有一个身份证
	private Card card; 
	省略getter和setter
}

Card.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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.CardMapper">

	<!-- 根据id查询Card,返回Card对象 -->
  <select id="selectCardById" parameterType="int" resultType="org.fkit.domain.Card">
  	SELECT * from tb_card where id = #{id} 
  </select>
  
</mapper>

PersonMapper.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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.PersonMapper">

	<!-- 根据id查询Person,返回resultMap -->
  <select id="selectPersonById" parameterType="int" 
  	resultMap="personMapper">
  	SELECT * from tb_person where id = #{id} 
  </select>

  <!-- 映射Peson对象的resultMap -->
	<resultMap type="org.fkit.domain.Person" id="personMapper">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<!-- 一对一关联映射:association   -->
		<association property="card" column="card_id"
		select="org.fkit.mapper.CardMapper.selectCardById" 
		javaType="org.fkit.domain.Card"/>
	</resultMap>

</mapper>

PersonMapper.java

package org.fkit.mapper;

import org.fkit.domain.Person;

public interface PersonMapper {
	
	/**
	 * 根据id查询Person
	 * 方法名和参数必须和XML文件中的<select.../>元素的id属性和parameterType属性一致
	 * @param id
	 * @return Person对象
	 * */
	Person selectPersonById(Integer id);
	
}

OneToOneTest.java

package org.fkit.test;

import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.fkit.domain.Person;
import org.fkit.mapper.PersonMapper;

public class OneToOneTest {

	public static void main(String[] args) throws Exception {
		// 读取mybatis-config.xml文件
		InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
		// 初始化mybatis,创建SqlSessionFactory类的实例
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
				.build(inputStream);
		// 创建Session实例
		SqlSession session = sqlSessionFactory.openSession();
		
		/*Person p 
		= session.selectOne("org.fkit.mapper.PersonMapper.selectPersonById",1);
		System.out.println(p);
		System.out.println(p.getCard().getCode());*/
		// 获得mapper接口的代理对象
		PersonMapper pm = session.getMapper(PersonMapper.class);
		// 直接调用接口的方法,查询id为1的Peson数据
		Person p = pm.selectPersonById(1);
		// 打印Peson对象
		System.out.println(p);
		// 打印Person对象关联的Card对象
		System.out.println(p.getCard());
		
		// 提交事务
		session.commit();
		// 关闭Session
		session.close();
	}

}

一对多映射

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Clazz.java

package org.fkit.domain;

import java.io.Serializable;
import java.util.List;

public class Clazz implements Serializable {
	
	private Integer id; // 班级id,主键
	private String code; // 班级编号
	private String name; // 班级名称
	
	// 班级和学生是一对多的关系,即一个班级可以有多个学生
	private List<Student> students;
	省略get/set方法
}

Student.java

public class Student implements Serializable {

	private Integer id; // 学生id,主键
	private String name; // 姓名
	private String sex;  // 性别
	private Integer age; // 年龄
	
	// 学生和班级是多对一的关系,即一个学生只属于一个班级
	private Clazz clazz;
	省略get和set方法
}

ClazzMapper.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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.ClazzMapper">

	<!-- 根据id查询班级信息,返回resultMap -->
	  <select id="selectClazzById" parameterType="int" resultMap="clazzResultMap">
	  	SELECT * FROM tb_clazz  WHERE id = #{id}
	  </select>
	  
	   <!-- 映射Clazz对象的resultMap -->
	<resultMap type="org.fkit.domain.Clazz" id="clazzResultMap">
		<id property="id" column="id"/>
		<result property="code" column="code"/>
		<result property="name" column="name"/>
		<!-- 一对多关联映射:collection fetchType="lazy"表示懒加载  -->
		<collection property="students" javaType="ArrayList"
	  column="id" ofType="org.fkit.domain.Student"
	  select="org.fkit.mapper.StudentMapper.selectStudentByClazzId"
	  fetchType="lazy">
	  	<id property="id" column="id"/>
	  	<result property="name" column="name"/>
	  	<result property="sex" column="sex"/>
	  	<result property="age" column="age"/>
	  </collection>
	</resultMap>
	
	
  

</mapper>

StudentMapper.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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.StudentMapper">

	<!-- 根据id查询学生信息,多表连接,返回resultMap -->
  <select id="selectStudentById" parameterType="int" resultMap="studentResultMap">
  	SELECT * FROM tb_clazz c,tb_student s
  	WHERE c.id = s.clazz_id
  	 AND s.id = #{id}
  </select>
  
  <!-- 根据班级id查询学生信息,返回resultMap -->
  <select id="selectStudentByClazzId" parameterType="int" 
  resultMap="studentResultMap">
  	SELECT * FROM tb_student WHERE clazz_id = #{id}
  </select>
  
   <!-- 映射Student对象的resultMap -->
	<resultMap type="org.fkit.domain.Student" id="studentResultMap">
		<id property="id" column="id"/>
	  	<result property="name" column="name"/>
	  	<result property="sex" column="sex"/>
	  	<result property="age" column="age"/>
		<!-- 多对一关联映射:association   -->
		<association property="clazz" javaType="org.fkit.domain.Clazz">
			<id property="id" column="id"/>
			<result property="code" column="code"/>
			<result property="name" column="name"/>
		</association>
	</resultMap>

</mapper>

多对多映射

在这里插入图片描述

在这里插入图片描述
User.java

public class User implements Serializable{
	
	private Integer id;  // 用户id,主键
	private String username;  // 用户名
	private String loginname; // 登录名
	private String password;  // 密码
	private String phone;    // 联系电话
	private String address;  // 收货地址
	
	// 用户和订单是一对多的关系,即一个用户可以有多个订单
	private List<Order> orders;

	省略get和set方法
}

在这里插入图片描述
Order.java

package org.fkit.domain;

import java.io.Serializable;
import java.util.List;

public class Order implements Serializable {

	private Integer id;  // 订单id,主键
	private String code;  // 订单编号
	private Double total; // 订单总金额
	
	// 订单和用户是多对一的关系,即一个订单只属于一个用户
	private User user;
	
	// 订单和商品是多对多的关系,即一个订单可以包含多种商品
	private List<Article> articles;

	省略get和set方法
}

在这里插入图片描述
Article.java

package org.fkit.domain;

import java.io.Serializable;
import java.util.List;

public class Article implements Serializable {
	
	private Integer id;		// 商品id,主键
	private String name;	// 商品名称
	private Double price;	// 商品价格
	private String remark;	// 商品描述
	
	// 商品和订单是多对多的关系,即一种商品可以包含在多个订单中
	private List<Order> orders;
	

}

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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.UserMapper">

	<resultMap type="org.fkit.domain.User" id="userResultMap">
		<id property="id" column="id"/>
		<result property="username" column="username"/>
		<result property="loginname" column="loginname"/>
		<result property="password" column="password"/>
		<result property="phone" column="phone"/>
		<result property="address" column="address"/>
		<!-- 一对多关联映射:collection   -->
		<collection property="orders" javaType="ArrayList"
	  column="id" ofType="org.fkit.domain.User"
	  select="org.fkit.mapper.OrderMapper.selectOrderByUserId"
	  fetchType="lazy">
	  	<id property="id" column="id"/>
	  	<result property="code" column="code"/>
	  	<result property="total" column="total"/>
	  </collection>
	</resultMap>
	
  <select id="selectUserById" parameterType="int" resultMap="userResultMap">
  	SELECT * FROM tb_user  WHERE id = #{id}
  </select>
  

</mapper>

UserMapper.java

package org.fkit.mapper;

import org.fkit.domain.User;

public interface UserMapper {
	
	User selectUserById(int id);

}

OrderMapper.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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.OrderMapper">

	<resultMap type="org.fkit.domain.Order" id="orderResultMap">
		<id property="id" column="oid"/>
	  	<result property="code" column="code"/>
	  	<result property="total" column="total"/>
		<!-- 多对一关联映射:association   -->
		<association property="user" javaType="org.fkit.domain.User">
			<id property="id" column="id"/>
			<result property="username" column="username"/>
			<result property="loginname" column="loginname"/>
			<result property="password" column="password"/>
			<result property="phone" column="phone"/>
			<result property="address" column="address"/>
		</association>
		<!-- 多对多映射的关键:collection   -->
		<collection property="articles" javaType="ArrayList"
	  column="oid" ofType="org.fkit.domain.Article"
	  select="org.fkit.mapper.ArticleMapper.selectArticleByOrderId"
	  fetchType="lazy">
	  	<id property="id" column="id"/>
	  	<result property="name" column="name"/>
	  	<result property="price" column="price"/>
	  	<result property="remark" column="remark"/>
	  </collection>
	</resultMap>
	
	<!-- 注意,如果查询出来的列同名,例如tb_user表的id和tb_order表的id都是id,同名,需要使用别名区分 -->
  <select id="selectOrderById" parameterType="int" resultMap="orderResultMap">
  	SELECT u.*,o.id AS oid,CODE,total,user_id
  	 FROM tb_user u,tb_order o
  	WHERE u.id = o.user_id
  	 AND o.id = #{id}
  </select>
  
  <!-- 根据userid查询订单 -->
  <select id="selectOrderByUserId" parameterType="int" resultType="org.fkit.domain.Order">
  	SELECT * FROM tb_order WHERE user_id = #{id}
  </select>
  

</mapper>

OrderMapper.java

package org.fkit.mapper;

import org.fkit.domain.Order;

public interface OrderMapper {

	Order selectOrderById(int id);
	
}

ArticleMapper.java
在这里插入图片描述

<?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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.ArticleMapper">
  
  <select id="selectArticleByOrderId" parameterType="int" 
  resultType="org.fkit.domain.Article">
  	SELECT * FROM tb_article WHERE id IN ( 
		SELECT article_id FROM tb_item WHERE order_id = #{id} 
	) 
  </select>
  

</mapper>

测试

package org.fkit.test;

import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.fkit.domain.Article;
import org.fkit.domain.Order;
import org.fkit.domain.User;
import org.fkit.mapper.OrderMapper;
import org.fkit.mapper.UserMapper;


public class ManyToManyTest {

	public static void main(String[] args) throws Exception {
		// 读取mybatis-config.xml文件
		InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
		// 初始化mybatis,创建SqlSessionFactory类的实例
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
				.build(inputStream);
		// 创建Session实例
		SqlSession session = sqlSessionFactory.openSession();
		
		ManyToManyTest t = new ManyToManyTest();
		
		// 根据用户id查询用户,测试一对多
//		t.testSelectUserById(session);
		// 根据订单id查询订单,测试多对多
		t.testSelectOrderById(session);
		
		// 提交事务
		session.commit();
		// 关闭Session
		session.close();
	}
	
	// 测试一对多,查询班级User(一)的时候级联查询订单Order(多)  
	public void testSelectUserById(SqlSession session){
		// 获得UserMapper接口的代理对象
		UserMapper um = session.getMapper(UserMapper.class);
		// 调用selectUserById方法
		User user = um.selectUserById(1);
		// 查看查询到的user对象信息
		System.out.println(user.getId() + " " + user.getUsername());
		// 查看user对象关联的订单信息
		List<Order> orders = user.getOrders();
		for(Order order : orders){
			System.out.println(order);
		}
	}
	
	// 测试多对多,查询订单Order(多)的时候级联查询订单的商品Article(多)  
	public void testSelectOrderById(SqlSession session){
		// 获得OrderMapper接口的代理对象
		OrderMapper om = session.getMapper(OrderMapper.class);
		// 调用selectOrderById方法
		Order order = om.selectOrderById(2);
		// 查看查询到的order对象信息
		System.out.println(order.getId() + " " + order.getCode() + " " + order.getTotal());
		// 查看order对象关联的用户信息
		User user = order.getUser();
		System.out.println(user);
		// 查看order对象关联的商品信息
		List<Article> articles = order.getArticles();
		for(Article article : articles){
			System.out.println(article);
		}
	}

}

动态SQL映射

EmployeeMapper.java

package org.fkit.mapper;

import java.util.HashMap;
import java.util.List;

import org.fkit.domain.Employee;

public interface EmployeeMapper {
	
	List<Employee> selectEmployeeByIdLike(HashMap<String, Object> params);
	
	List<Employee> selectEmployeeByLoginLike(HashMap<String, Object> params);
	
	List<Employee> selectEmployeeChoose(HashMap<String, Object> params);
	
	List<Employee> findEmployeeLike(HashMap<String, Object> params);
	
	List<Employee> selectEmployeeLike(HashMap<String, Object> params);
	
	Employee selectEmployeeWithId(Integer id);
	
	void updateEmployeeIfNecessary(Employee employee);
	
	List<Employee> selectEmployeeIn(List<Integer> ids);
	
	List<Employee> selectEmployeeLikeName(Employee employee);
	

}

EmployeeMapper.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">
<!-- namespace指用户自定义的命名空间。 -->
<mapper namespace="org.fkit.mapper.EmployeeMapper">

	<select id="selectEmployeeWithId" parameterType="int" resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee where id = #{id}
  </select>
	
  <!-- if -->
  <select id="selectEmployeeByIdLike" 
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee WHERE state = 'ACTIVE'
  	<!-- 可选条件,如果传进来的参数有id属性,则加上id查询条件 -->
  	<if test="id != null ">
  		and id = #{id}
  	</if>
  </select>
  
  <!-- if -->
  <select id="selectEmployeeByLoginLike" 
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee WHERE state = 'ACTIVE'
  	<!-- 两个可选条件,例如登录功能的登录名和密码查询 -->
  	<if test="loginname != null and password != null">
  		and loginname = #{loginname} and password = #{password}
  	</if>
  </select>
  
  <!-- choose(when、otherwise) -->
  <select id="selectEmployeeChoose" 
  	parameterType="hashmap" 
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee WHERE state = 'ACTIVE'
  	<!-- 如果传入了id,就根据id查询,没有传入id就根据loginname和password查询,否则查询sex等于男的数据 -->
  	<choose>
  		<when test="id != null">
  			and id = #{id}
  		</when>
  		<when test="loginname != null and password != null">
  			and loginname = #{loginname} and password = #{password}
  		</when>
  		<otherwise>
  			and sex = '男'
  		</otherwise>
  	</choose>
  </select>
  
  <select id="findEmployeeLike"  
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee WHERE 
  	<if test="state != null ">
  		state = #{state}
  	</if>
  	<if test="id != null ">
  		and id = #{id}
  	</if>
  	<if test="loginname != null and password != null">
  		and loginname = #{loginname} and password = #{password}
  	</if>
  </select>
  
  <!-- where -->
  <select id="selectEmployeeLike" 
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee  
  	<where>
  		<if test="state != null ">
  			state = #{state}
	  	</if>
	  	<if test="id != null ">
	  		and id = #{id}
	  	</if>
	  	<if test="loginname != null and password != null">
	  		and loginname = #{loginname} and password = #{password}
	  	</if>
  	</where>
  </select>
  
  <!-- set -->
  <update id="updateEmployeeIfNecessary" 
  	parameterType="org.fkit.domain.Employee">
	  update tb_employee
	    <set>
	      <if test="loginname != null">loginname=#{loginname},</if>
	      <if test="password != null">password=#{password},</if>
	      <if test="name != null">name=#{name},</if>
	      <if test="sex != null">sex=#{sex},</if>
	      <if test="age != null">age=#{age},</if>
	      <if test="phone != null">phone=#{phone},</if>
	      <if test="sal != null">sal=#{sal},</if>
	      <if test="state != null">state=#{state}</if>
	    </set>
	  where id=#{id}
	</update>
  
  <!-- foreach -->
  <select id="selectEmployeeIn" resultType="org.fkit.domain.Employee">
	  SELECT *
	  FROM tb_employee
	  WHERE ID in
	  <foreach item="item" index="index" collection="list"
	      open="(" separator="," close=")">
	        #{item}
	  </foreach>
  </select>
  
  <!-- bind -->
	<select id="selectEmployeeLikeName"  resultType="org.fkit.domain.Employee">
	  <bind name="pattern" value="'%' + _parameter.getName() + '%'" />
	  	SELECT * FROM tb_employee
	  	WHERE loginname LIKE #{pattern}
	</select>

</mapper>

if

<!-- if -->
  <select id="selectEmployeeByIdLike" 
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee WHERE state = 'ACTIVE'
  	<!-- 可选条件,如果传进来的参数有id属性,则加上id查询条件 -->
  	<if test="id != null ">
  		and id = #{id}
  	</if>
  </select>
  
  <!-- if -->
  <select id="selectEmployeeByLoginLike" 
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee WHERE state = 'ACTIVE'
  	<!-- 两个可选条件,例如登录功能的登录名和密码查询 -->
  	<if test="loginname != null and password != null">
  		and loginname = #{loginname} and password = #{password}
  	</if>
  </select>

choose (when、 otherwise)(如果条件成立执行when中判断)

<!-- choose(when、otherwise) -->
  <select id="selectEmployeeChoose" 
  	parameterType="hashmap" 
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee WHERE state = 'ACTIVE'
  	<!-- 如果传入了id,就根据id查询,没有传入id就根据loginname和password查询,否则查询sex等于男的数据 -->
  	<choose>
  		<when test="id != null">
  			and id = #{id}
  		</when>
  		<when test="loginname != null and password != null">
  			and loginname = #{loginname} and password = #{password}
  		</when>
  		<otherwise>
  			and sex = '男'
  		</otherwise>
  	</choose>
  </select>

where

在这里插入图片描述
直接写where当有一个参数没有值会报错

<!-- where -->
  <select id="selectEmployeeLike" 
  	resultType="org.fkit.domain.Employee">
  	SELECT * FROM tb_employee  
  	<where>
  		<if test="state != null ">
  			state = #{state}
	  	</if>
	  	<if test="id != null ">
	  		and id = #{id}
	  	</if>
	  	<if test="loginname != null and password != null">
	  		and loginname = #{loginname} and password = #{password}
	  	</if>
  	</where>
  </select>

set

在这里插入图片描述


update tb_employee

loginname=#{loginname},
password=#{password},
name=#{name},
sex=#{sex},
age=#{age},
phone=#{phone},
sal=#{sal},
state=#{state}

where id=#{id}

foreach

循环

<!-- foreach -->
  <select id="selectEmployeeIn" resultType="org.fkit.domain.Employee">
	  SELECT *
	  FROM tb_employee
	  WHERE ID in
	  <foreach item="item" index="index" collection="list"
	      open="(" separator="," close=")">
	        #{item}
	  </foreach>
  </select>

bind

在这里插入图片描述

<!-- bind -->
	<select id="selectEmployeeLikeName"  resultType="org.fkit.domain.Employee">
	  <bind name="pattern" value="'%' + _parameter.getName() + '%'" />
	  	SELECT * FROM tb_employee
	  	WHERE loginname LIKE #{pattern}
	</select>

猜你喜欢

转载自blog.csdn.net/qq_32754539/article/details/89886072
今日推荐