mybatis高級映射多對多查詢(二)

在這篇博客中,我來介紹下mybatis中的多對多查詢的案例,在mybatis中,如何使用ResultMap來實現多對多的查詢?

案例:一個user可以有很多role,一個role可以有很多entitlement.

一,數據庫表的準備

<span style="font-size:18px;">DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) COLLATE utf8_bin NOT NULL,
  `sex` varchar(20) COLLATE utf8_bin NOT NULL,
  `birthday` date NOT NULL,
  `address` varchar(20) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('5', '步驚雲', '男', '2016-03-12', '安徽');
INSERT INTO `user` VALUES ('6', '聶風', '男', '2016-03-01', '上海');
INSERT INTO `user` VALUES ('7', '楊康', '男', '2016-03-03', '杭州');</span>

<span style="font-size:18px;">-- ----------------------------
-- Table structure for `role`
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `rolename` varchar(20) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', '管理員');
INSERT INTO `role` VALUES ('2', '用戶模塊管理員');
INSERT INTO `role` VALUES ('3', '國家模塊管理員');</span>


<span style="font-size:18px;">DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  KEY `user_foreign_key` (`user_id`),
  KEY `role_foreign_key` (`role_id`),
  CONSTRAINT `role_foreign_key` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`),
  CONSTRAINT `user_foreign_key` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES ('5', '1');
INSERT INTO `user_role` VALUES ('5', '2');
INSERT INTO `user_role` VALUES ('6', '2');
INSERT INTO `user_role` VALUES ('7', '1');
INSERT INTO `user_role` VALUES ('7', '2');
INSERT INTO `user_role` VALUES ('7', '3');</span>

<span style="font-size:18px;">DROP TABLE IF EXISTS `entitlement`;
CREATE TABLE `entitlement` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `entitlementname` varchar(20) COLLATE utf8_bin NOT NULL,
  `role_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `role_entitlement_foreign_key` (`role_id`),
  CONSTRAINT `role_entitlement_foreign_key` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of entitlement
-- ----------------------------
INSERT INTO `entitlement` VALUES ('1', '添加', '1');
INSERT INTO `entitlement` VALUES ('2', '修改', '1');
INSERT INTO `entitlement` VALUES ('3', '添加', '2');
INSERT INTO `entitlement` VALUES ('4', '修改', '2');
INSERT INTO `entitlement` VALUES ('5', '刪除', '2');
INSERT INTO `entitlement` VALUES ('6', '添加', '3');</span>


二,與數據庫表對應的entity的類結構

package com.npf.entity;

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

public class User implements Serializable {

	private static final long serialVersionUID = 8341195547209659206L;

	private int id;
	private String username;
	private String sex;
	private Date birthday;
	private String address;
	private List<Role> roles;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public List<Role> getRoles() {
		return roles;
	}

	public void setRoles(List<Role> roles) {
		this.roles = roles;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", sex=" + sex
				+ ", birthday=" + birthday + ", address=" + address
				+ ", roles=" + roles + "]";
	}
}

package com.npf.entity;

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

/**
 * 
 * @author Jack
 *
 */
public class Role implements Serializable{

	private static final long serialVersionUID = -3687052298547500972L;
	
	private Integer id;
	
	private String rolename;
	
	private List<Entitlement> entitlements;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getRolename() {
		return rolename;
	}

	public void setRolename(String rolename) {
		this.rolename = rolename;
	}

	public List<Entitlement> getEntitlements() {
		return entitlements;
	}

	public void setEntitlements(List<Entitlement> entitlements) {
		this.entitlements = entitlements;
	}

	@Override
	public String toString() {
		return "Role [id=" + id + ", rolename=" + rolename + ", entitlements="
				+ entitlements + "]";
	}
}

package com.npf.entity;

import java.io.Serializable;

/**
 * 
 * @author Jack
 *
 */
public class Entitlement implements Serializable{

	private static final long serialVersionUID = -1630305760044848905L;
	
	private Integer id;
	
	private String entitlementname;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getEntitlementname() {
		return entitlementname;
	}

	public void setEntitlementname(String entitlementname) {
		this.entitlementname = entitlementname;
	}

	@Override
	public String toString() {
		return "Entitlement [id=" + id + ", entitlementname=" + entitlementname
				+ "]";
	}

}

三,mapper接口和mapper.xml配置文件(注意這兩個文件需要放在同一個包下面)

package com.npf.user.mapper;

import java.util.List;
import java.util.Map;

import com.npf.entity.User;
import com.npf.entity.vo.UserQueryVO;

public interface UserMapper {

	public List<User> findUserRoleEntitlement() throws Exception;

}


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">

<mapper namespace="com.npf.user.mapper.UserMapper">

	<resultMap type="com.npf.entity.User" id="findUserRoleEntitlementResultMap">
		<id column="user_id" property="id"/>
		<result column="username" property="username"/>
		<result column="sex" property="sex"/>
		<result column="birthday" property="birthday"/>
		<result column="address" property="address"/>
		<collection property="roles" ofType="com.npf.entity.Role">
			<id column="role_id" property="id"/>
			<result column="rolename" property="rolename"/>
			<collection property="entitlements" ofType="com.npf.entity.Entitlement">
				<id column="entitlement_id" property="id"/>
				<result column="entitlementname" property="entitlementname"/>
			</collection>
		</collection>
	</resultMap>

	<select id="findUserRoleEntitlement" resultMap="findUserRoleEntitlementResultMap">
		select 
			`user`.id as user_id,
			`user`.username as username,
			`user`.sex as sex,
			`user`.birthday as birthday,
			`user`.address as address,
			 user_role.role_id,
			 role.rolename as rolename,
			 entitlement.entitlementname,
			 entitlement.id as entitlement_id
		from user inner JOIN user_role ON 
			`user`.id = user_role.user_id 
		inner JOIN role on role.id = user_role.role_id
		inner JOIN entitlement ON entitlement.role_id = role.id;
	</select>
</mapper>


四,mybatis的核心配置文件

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 resource="db.properties"></properties>

	<!-- 和spring整合後 environments配置將廢除-->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事務管理,事務控制由mybatis-->
			<transactionManager type="JDBC" />
			<!-- 數據庫連接池,由mybatis管理-->
			<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>
		</environment>
	</environments>
	
	<!-- 加載映射文件 -->
	<mappers>
		<package name="com.npf.user.mapper"/>
	</mappers>
</configuration>

五,獲取SqlSessionFactory的工具類

package com.npf.utils;

import java.io.IOException;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public final class MyBatisUtils {
	
	private static SqlSessionFactory sqlSessionFactory;
	
	private static final String resource = "SqlMapConfig.xml";
	
	private MyBatisUtils(){}
	
	public static SqlSessionFactory getSqlSessionFactory(){
		if(sqlSessionFactory==null){
			synchronized (MyBatisUtils.class) {
				if(sqlSessionFactory==null){
					try {
						sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(resource));
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return sqlSessionFactory;
	}

}

六,測試

package com.npf.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Before;
import org.junit.Test;

import com.npf.entity.User;
import com.npf.user.mapper.UserMapper;
import com.npf.utils.MyBatisUtils;

public class UserMapperTest {

	private SqlSessionFactory sessionFactory;
	
	@Before
	public void setup(){
		sessionFactory = MyBatisUtils.getSqlSessionFactory();
	}
	
	@Test
	public void findUserRoleEntitlementTest() throws Exception{
		SqlSession session = sessionFactory.openSession();
		UserMapper usermapper = session.getMapper(UserMapper.class);
		List<User> users = usermapper.findUserRoleEntitlement();
		for(User user : users){
			System.out.println(user);
		}
	}
	
}

七,運行結果

DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 939437404.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@37fead5c]
DEBUG [main] - ==>  Preparing: select `user`.id as user_id, `user`.username as username, `user`.sex as sex, `user`.birthday as birthday, `user`.address as address, user_role.role_id, role.rolename as rolename, entitlement.entitlementname, entitlement.id as entitlement_id from user inner JOIN user_role ON `user`.id = user_role.user_id inner JOIN role on role.id = user_role.role_id inner JOIN entitlement ON entitlement.role_id = role.id; 
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 14
User [id=5, username=步驚雲, sex=男, birthday=Sat Mar 12 00:00:00 CST 2016, address=安徽, roles=[Role [id=1, rolename=管理員, entitlements=[Entitlement [id=1, entitlementname=添加], Entitlement [id=2, entitlementname=修改]]], Role [id=2, rolename=用戶模塊管理員, entitlements=[Entitlement [id=3, entitlementname=添加], Entitlement [id=4, entitlementname=修改], Entitlement [id=5, entitlementname=刪除]]]]]
User [id=6, username=聶風, sex=男, birthday=Tue Mar 01 00:00:00 CST 2016, address=上海, roles=[Role [id=2, rolename=用戶模塊管理員, entitlements=[Entitlement [id=3, entitlementname=添加], Entitlement [id=4, entitlementname=修改], Entitlement [id=5, entitlementname=刪除]]]]]
User [id=7, username=楊康, sex=男, birthday=Thu Mar 03 00:00:00 CST 2016, address=杭州, roles=[Role [id=1, rolename=管理員, entitlements=[Entitlement [id=1, entitlementname=添加], Entitlement [id=2, entitlementname=修改]]], Role [id=2, rolename=用戶模塊管理員, entitlements=[Entitlement [id=3, entitlementname=添加], Entitlement [id=4, entitlementname=修改], Entitlement [id=5, entitlementname=刪除]]], Role [id=3, rolename=國家模塊管理員, entitlements=[Entitlement [id=6, entitlementname=添加]]]]]

八,總結

1. 使用resultMap是針對那些對查詢結果映射有特殊要求的功能,,比如特殊要求映射成list中包括 多個list。

2. resultType:作用:將查詢結果按照sql列名pojo屬性名一致性映射到pojo中。

   場合:常見一些明細記錄的展示,比如用戶購買商品明細,將關聯查詢信息全部展示在頁面時,此時可直接使用                   resultType將每一條記錄映射到pojo中,在前端頁面遍歷list(list中是pojo)即可。

   resultMap:使用association和collection完成一對一和一對多高級映射(對結果有特殊的映射要求)。

   association:作用:將關聯查詢信息映射到一個pojo對象中。

   場合:爲了方便查詢關聯信息可以使用association將關聯訂單信息映射爲用戶對象的pojo屬性中,比如:查詢訂單                及關聯用戶信息。使用resultType無法將查詢結果映射到pojo對象的pojo屬性中,根據對結果集查詢遍歷的需              要選擇使用resultType還是resultMap。

    collection:作用:將關聯查詢信息映射到一個list集合中。

    場合:爲了方便查詢遍歷關聯信息可以使用collection將關聯信息映射到list集合中,比如:查詢用戶權限範圍模塊       及模塊下的菜單,可使用collection將模塊映射到模塊list中,將菜單列表映射到模塊對象的菜單list屬性中,這樣的       作的目的也是方便對查詢結果集進行遍歷查詢。如果使用resultType無法將查詢結果映射到list集合中。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章