精华内容
下载资源
问答
  • 一对一的映射
    万次阅读 多人点赞
    2017-05-18 17:46:43

    mybatis-generator这是原来的github地址
    现在在此基础上添加了一对一和一对多映射配置,配置在table标签上
    如果需要一对一配置生成,需要添加插件配置
    在context中添加如下配置

    <!-- 生成一对一配置 -->
    <plugin type="cc.bandaotixi.plugins.OneToOnePlugin"></plugin>
    

    一对多配置如下

    <!-- 生成一对多配置 -->
    <plugin type="cc.bandaotixi.plugins.OneToManyPlugin"></plugin>
    

    批量插入和批量更新

    <plugin type="cc.bandaotixi.plugins.BatchInsertPlugin"></plugin>
    <plugin type="cc.bandaotixi.plugins.BatchUpdatePlugin"></plugin>
    

    如果需要把数据库注释添加到java文件中,配置如下

    <commentGenerator type="cc.bandaotixi.plugins.BDTCommentGenerator">
     	<property name="javaFileEncoding" value="UTF-8"/>
    	<property name="suppressDate" value="true"/>
    	<property name="suppressAllComments" value="false" /></commentGenerator>
    

    那么配置一对一表时应这么配置

    <table tableName="t_test" domainObjectName="TEst">
     	<generatedKey column="test_id" sqlStatement="MySql" identity="true" />
     	<oneToOne mappingTable="t_test" column="test_id" joinColumn="parent_test_id" where="t_test.is_deleted=0" />
     </table>
    

    配置一对多表时

    <table tableName="t_test" domainObjectName="Test">
     	<generatedKey column="test_id" sqlStatement="MySql" identity="true" />
     	<oneToMany mappingTable="t_test" column="test_id" joinColumn="parent_test_id" where="t_test.is_deleted=0" />
     </table>
    

    下面补上全部配置

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    <!--
    生成mapper命令
    java -jar mybatis.jar -configfile generatorConfig.xml -overwrite
    -->
    <generatorConfiguration>
    	<classPathEntry location="C:\Users\administrator\.m2\repository\mysql\mysql-connector-java\5.1.39\mysql-connector-java-5.1.39.jar" />
     	<context id="appInfo" targetRuntime="MyBatis3">
     		<property name="javaFileEncoding" value="UTF-8"/>
     		<!-- 生成一对一配置 -->
    		<plugin type="cc.bandaotixi.plugins.OneToOnePlugin"></plugin>
    		<!-- 生成一对多配置 -->
    		<plugin type="cc.bandaotixi.plugins.OneToManyPlugin"></plugin>
    		<plugin type="cc.bandaotixi.plugins.BatchInsertPlugin"></plugin>
    		<plugin type="cc.bandaotixi.plugins.BatchUpdatePlugin"></plugin>
     		<commentGenerator type="cc.bandaotixi.plugins.BDTCommentGenerator">
    	        <property name="suppressDate" value="true"/>
    	        <property name="suppressAllComments" value="false" />
    	    </commentGenerator>
     		<jdbcConnection connectionURL="jdbc:mysql://localhost:3307/test?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true" driverClass="com.mysql.jdbc.Driver" password="test" userId="root" />
     		<!-- 数据表对应的实体层 -->
    		<javaModelGenerator targetPackage="com.entity"
    			targetProject="src/main/java">
    			<property name="enableSubPackages" value="true" />
    			<property name="trimStrings" value="true" />
    		</javaModelGenerator>
    		
     		<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
     			<property name="enableSubPackages" value="true" />
    			<property name="isMergeable" value="false"/>
     		</sqlMapGenerator>
     		
     		<!-- 在ibatis2 中是dao层,但在mybatis3中,其实就是mapper接口 -->
     		<javaClientGenerator type="XMLMAPPER" targetPackage="com.dao" targetProject="src/main/java">
    			<property name="enableSubPackages" value="true" />
    		</javaClientGenerator>
    
     		<table tableName="t_test" domainObjectName="Test">
     			<generatedKey column="test_id" sqlStatement="MySql" identity="true" />
     			<oneToMany mappingTable="t_test" column="parent_est_id" joinColumn="test_id" where="t_test.is_deleted=0" />
                            <!--映射的表必须配置table-->
     		</table>
     	</context>
    </generatorConfiguration>
    

    值得注意的是,如果使用批量更新功能需要在连接的配置上添加allowMultiQueries=true
    如果你比较懒,不想编译代码也可以直接下载,但是需要一个积分
    如果需要进一步添加插件,请fork郗瑞强MybatisGenerator工具
    如果有问题或者BUG请发邮件到:bandaotixi@hotmail.com
    感谢

    很抱歉,因为代码很久远,这里已经不再维护,请理解

    更多相关内容
  • 方式一:使用自动映射处理一对一映射 实体类改造 UserMapper接口增加接口方法 UserMapper.xml增加SQL 单元测试 方式二:使用resultMap配置一对一映射 UserMapper接口增加接口方法 UserMapper.xml增加SQL 单元测试 ...

    概述

    我们还是继续使用我们的RBAC权限系统来演示。

    假设在RBAC权限系统中,一个用户只能拥有一个角色。


    需求

    实现在查询用户信息的同时获取用户拥有的角色信息


    方式一:使用自动映射处理一对一映射

    实体类改造

    一个用户拥有一个角色,因此现在SysUser类中增加SysRole字段

    /**
     * 
     * 
     * @ClassName: SysUser
     * 
     * @Description: 用户表
     * 
     * @author: Mr.Yang
     * 
     * @date: 2018年4月13日 下午9:24:21
     */
    public class SysUser  {
    
    	//其他原有字段以及setter getter
    
    	/**
    	 * 用户角色
    	 */
    	private SysRole sysRole;
    	
    	// setter getter
    	public SysRole getSysRole() {
    		return sysRole;
    	}
    
    	public void setSysRole(SysRole sysRole) {
    		this.sysRole = sysRole;
    	}
    
    	
    }
    

    使用自动映射就是通过别名让MyBatis自动将值匹配到对应的子弹上,简单的别名映射如user_name 对应userName .

    除此之外MyBatis还支持复杂的属性映射,可以多层嵌套。 比如将role.role_name 映射到 role.roleName上。 MyBatis首先会查找role属性,如果存在role属性就创建role对象,然后在role对象中继续查找roleName, 将role_name的值绑定到role对象的roleName属性上 。


    UserMapper接口增加接口方法

    /**
    	 * 
    	 * 
    	 * @Title: selectSysUserAndSysRoleById
    	 * 
    	 * @Description: 根据Id查询用户信息的同时获取用户拥有的角色信息
    	 * 
    	 * @param id
    	 * @return
    	 * 
    	 * @return: SysUser
    	 */
    	SysUser selectSysUserAndSysRoleById(Long id);
    

    UserMapper.xml增加SQL

    <select id="selectSysUserAndSysRoleById" resultType="com.artisan.mybatis.xml.domain.SysUser">
    		SELECT
    			u.id,
    			u.user_name userName,
    			u.user_password userPassword,
    			u.user_email userEmail,
    			u.user_info userInfo,
    			u.create_time createTime,
    			u.head_img headImg,
    			r.id "sysRole.id",
    			r.role_name "sysRole.roleName",
    			r.enabled "sysRole.enabled",
    			r.create_by "sysRole.createBy",
    			r.create_time "sysRole.createTime"
    		FROM
    			sys_user u
    		INNER JOIN sys_user_role ur ON u.id = ur.user_id
    		INNER JOIN sys_role r ON ur.role_id = r.id
    		WHERE
    			u.id = #{id}
    	</select>
    

    注意上述SQL中 sys_role查询的列的别名都是 “sysRole.”前缀,这和SysUser实体类中SysRole属性的名称保持一致,通过这种方式将sysRole的属性都映射到了SysUser的sysRole属性上


    单元测试

    @Test
    	public void selectSysUserAndSysRoleByIdTest() {
    		logger.info("selectSysUserAndSysRoleByIdTest");
    		// 获取SqlSession
    		SqlSession sqlSession = getSqlSession();
    		try {
    			// 获取UserMapper接口
    			UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    			// 注意:数据库中id=1的用户拥有2个角色,不适合这个例子。
    			// 调用selectSysUserAndSysRoleById方法,查询id=1001的用户及其角色
    			SysUser sysUser = userMapper.selectSysUserAndSysRoleById(1001L);
    			// 期望用户不为空
    			Assert.assertNotNull(sysUser);
    			// 期望角色不为空
    			Assert.assertNotNull(sysUser.getSysRole());
    
    			logger.info(sysUser);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			sqlSession.close();
    			logger.info("sqlSession close successfully ");
    		}
    	}
    

    debug调测下数据

    这里写图片描述


    日志

    2018-04-29 23:43:15,905  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
    2018-04-29 23:43:15,913  INFO [main] (BaseMapperTest.java:29) - reader close successfully
    2018-04-29 23:43:15,918  INFO [main] (UserMapperTest.java:1007) - selectSysUserAndSysRoleByIdTest
    2018-04-29 23:43:16,008 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT u.id, u.user_name userName, u.user_password userPassword, u.user_email userEmail, u.user_info userInfo, u.create_time createTime, u.head_img headImg, r.id "sysRole.id", r.role_name "sysRole.roleName", r.enabled "sysRole.enabled", r.create_by "sysRole.createBy", r.create_time "sysRole.createTime" FROM sys_user u INNER JOIN sys_user_role ur ON u.id = ur.user_id INNER JOIN sys_role r ON ur.role_id = r.id WHERE u.id = ? 
    2018-04-29 23:43:16,135 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1001(Long)
    2018-04-29 23:43:16,196 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, createTime, headImg, sysRole.id, sysRole.roleName, sysRole.enabled, sysRole.createBy, sysRole.createTime
    2018-04-29 23:43:16,198 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1001, artisan, 123456, test@artisan.com, <<BLOB>>, 2018-04-13 21:12:47.0, <<BLOB>>, 2, 普通用户, 1, 1, 2018-04-13 21:12:46.0
    2018-04-29 23:43:16,215 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
    2018-04-29 23:43:16,216  INFO [main] (UserMapperTest.java:1021) - SysUser [id=1001, userName=artisan, userPassword=123456, userEmail=test@artisan.com, userInfo=测试用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018, sysRole=SysRole [id=2, roleName=普通用户, enabled=1, createBy=1, createTime=Fri Apr 13 21:12:46 BOT 2018, user=null, privilegeList=null]]
    2018-04-29 23:43:16,222  INFO [main] (UserMapperTest.java:1026) - sqlSession close successfully 
    
    
    

    通过SQL日志可以看到已经查询出的一条数据,MyBatis将这条数据映射到了两个类中,像这种通过一次查询将结果映射到不同对象的方式,称之为关联的嵌套结果查询。

    关联的嵌套结果映射需要关联多个表将所有需要的值一次性查询出来, 这种方式的好处是减少数据库的查询次数,减轻数据库的压力。 缺点是需要些很复杂的SQL,并且当嵌套结果更负载时,不容易一次写正确。 由于要在服务器上将结果映射到不同的类上,因此也会增加应用服务器的压力。 当一定会使用到嵌套查询,并且整个复杂的SQL执行速度很快时,建议使用关联的其那套结果查询。


    方式二:使用resultMap配置一对一映射

    UserMapper接口增加接口方法

    // 使用resultMap配置一对一映射
    SysUser selectSysUserAndSysRoleById2(Long id);
    

    UserMapper.xml增加SQL

    <!-- 使用resultMap配置一对一映射 -->
    	<resultMap id="userRoleMap" 
    			   type="com.artisan.mybatis.xml.domain.SysUser">
    		<id column="id" property="id" />
    		<result property="userName" column="user_name" />
    		<result property="userPassword" column="user_password" />
    		<result property="userEmail" column="user_email" />
    		<result property="userInfo" column="user_info" />
    		<result property="headImg" column="head_img" jdbcType="BLOB" />
    		<result property="createTime" column="create_time" jdbcType="TIMESTAMP" />
    		<!-- sysRole相关的属性 -->
    		<result property="sysRole.id" column="role_id"/>
    		<result property="sysRole.roleName" column="role_name"/>
    		<result property="sysRole.enabled" column="enabled"/>
    		<result property="sysRole.createBy" column="create_by"/>
    		<result property="sysRole.createTime" column="role_create_time" jdbcType="TIMESTAMP"/>
    	</resultMap>
    

    这种配置和上一个配置相似的地方在于,sysRole中的property配置部分使用“sysRole.”前缀,在column部分,为了避免不同表中存在相同的的字段,所有可能重名的列都加了 “role_”前缀。

    这种方式配置的时候,还需要再查询时设置不同的列名,别名和resultMap配置的colunm一致。 然后使用resultMap配置映射。

    <!-- 使用resultMap配置一对一映射 -->
    	<select id="selectSysUserAndSysRoleById2" resultMap="userRoleMap">
    		SELECT
    			u.id,
    			u.user_name ,
    			u.user_password ,
    			u.user_email ,
    			u.user_info ,
    			u.create_time ,
    			u.head_img ,
    			r.id role_id,
    			r.role_name ,
    			r.enabled ,
    			r.create_by ,
    			r.create_time role_create_time 
    		FROM
    			sys_user u
    		INNER JOIN sys_user_role ur ON u.id = ur.user_id
    		INNER JOIN sys_role r ON ur.role_id = r.id
    		WHERE
    			u.id = #{id}
    	</select>
    

    单元测试

    @Test
    	public void selectSysUserAndSysRoleById2Test() {
    		logger.info("selectSysUserAndSysRoleById2Test");
    		// 获取SqlSession
    		SqlSession sqlSession = getSqlSession();
    		try {
    			// 获取UserMapper接口
    			UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    			// 注意:数据库中id=1的用户拥有2个角色,不适合这个例子。
    			// 调用selectSysUserAndSysRoleById方法,查询id=1001的用户及其角色
    			SysUser sysUser = userMapper.selectSysUserAndSysRoleById2(1001L);
    			// 期望用户不为空
    			Assert.assertNotNull(sysUser);
    			// 期望角色不为空
    			Assert.assertNotNull(sysUser.getSysRole());
    
    			logger.info(sysUser);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			sqlSession.close();
    			logger.info("sqlSession close successfully ");
    		}
    	}
    	
    

    日志

    2018-04-30 00:52:25,287  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
    2018-04-30 00:52:25,291  INFO [main] (BaseMapperTest.java:29) - reader close successfully
    2018-04-30 00:52:25,295  INFO [main] (UserMapperTest.java:1032) - selectSysUserAndSysRoleById2Test
    2018-04-30 00:52:25,390 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT u.id, u.user_name , u.user_password , u.user_email , u.user_info , u.create_time , u.head_img , r.id role_id, r.role_name , r.enabled , r.create_by , r.create_time role_create_time FROM sys_user u INNER JOIN sys_user_role ur ON u.id = ur.user_id INNER JOIN sys_role r ON ur.role_id = r.id WHERE u.id = ? 
    2018-04-30 00:52:25,519 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1001(Long)
    2018-04-30 00:52:25,559 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, user_name, user_password, user_email, user_info, create_time, head_img, role_id, role_name, enabled, create_by, role_create_time
    2018-04-30 00:52:25,561 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1001, artisan, 123456, test@artisan.com, <<BLOB>>, 2018-04-13 21:12:47.0, <<BLOB>>, 2, 普通用户, 1, 1, 2018-04-13 21:12:46.0
    2018-04-30 00:52:25,572 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
    2018-04-30 00:52:25,573  INFO [main] (UserMapperTest.java:1046) - SysUser [id=1001, userName=artisan, userPassword=123456, userEmail=test@artisan.com, userInfo=测试用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018, sysRole=SysRole [id=2, roleName=普通用户, enabled=1, createBy=1, createTime=Fri Apr 13 21:12:46 BOT 2018, user=null, privilegeList=null]]
    2018-04-30 00:52:25,580  INFO [main] (UserMapperTest.java:1051) - sqlSession close successfully 
    
    

    这种方法是不是和第一种使用自动映射处理一对一映射相比起来,resultMap相当麻烦?

    事实上 ,resultMap映射是可以被继承的,因此要先简化上面的resultMap的配置。 因为我们这个映射文件中本来就存在一个userMap的映射配置,改造如下

    <!-- 使用resultMap配置一对一映射  继承原有的resultMap -->
    	<resultMap id="userRoleMap_byExtends"  extends="userMap"
    			   type="com.artisan.mybatis.xml.domain.SysUser">
    		<!-- sysRole相关的属性 -->
    		<result property="sysRole.id" column="role_id"/>
    		<result property="sysRole.roleName" column="role_name"/>
    		<result property="sysRole.enabled" column="enabled"/>
    		<result property="sysRole.createBy" column="create_by"/>
    		<result property="sysRole.createTime" column="role_create_time" jdbcType="TIMESTAMP"/>
    	</resultMap>
    	
    

    使用继承不仅可以简化配置,而且当对主表userMap进行修改时也只需要修改一处。 虽然还不是太方便,至少简洁了一点。 要想更加简洁,只有派上asscociation了,请往下看

    测试过了,就不贴代码了,github上已经托管。


    方式三:使用resultMap的asscociation标签配置一对一映射

    在resultMap中,association标签用于和一个复杂的类型进行关联,即用于一对一的关联配置。

    UserMapper接口增加接口方法

    // 使用resultMap配置一对一映射 resultMap association
    SysUser selectSysUserAndSysRoleById4(Long id);
    

    UserMapper.xml增加SQL

    在上面的基础上,再做修改,改成association标签的配置方式。

    	<!-- 使用resultMap配置一对一映射  使用association -->
    	<resultMap id="userRoleMap_byExtendsAndAssociation"  extends="userMap"
    			   type="com.artisan.mybatis.xml.domain.SysUser">
    		<association property="sysRole" columnPrefix="sysRole_"
    			javaType="com.artisan.mybatis.xml.domain.SysRole">
    			<result property="id" column="id"/>
    			<result property="roleName" column="role_name"/>
    			<result property="enabled" column="enabled"/>
    			<result property="createBy" column="create_by"/>
    			<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
    		</association>	   
    	</resultMap>
    	
    
    
    <!-- 使用resultMap配置一对一映射 result中Map中使用association  -->
    	<select id="selectSysUserAndSysRoleById4" resultMap="userRoleMap_byExtendsAndAssociation">
    		SELECT
    			u.id,
    			u.user_name ,
    			u.user_password ,
    			u.user_email ,
    			u.user_info ,
    			u.create_time ,
    			u.head_img ,
    			r.id sysRole_id,
    			r.role_name sysRole_role_name,
    			r.enabled sysRole_enabled,
    			r.create_by sysRole_create_by,
    			r.create_time sysRole_create_time
    		FROM
    			sys_user u
    		INNER JOIN sys_user_role ur ON u.id = ur.user_id
    		INNER JOIN sys_role r ON ur.role_id = r.id
    		WHERE
    			u.id = #{id}
    	</select>
    
    
    

    association标签包含如下主要属性

    • property:对应实体列中的属性名,必填
    • javaType:属性对应的Java类型
    • resultMap:可以直接使用现有的resultMap,从而不需要在这里配置
    • colunmPrefix: 查询列的前缀,配置前缀后,在子标签配置result的colunm时,可以省略前缀
    • 其他属性,略…

    因为配置了列的前缀,因此还需要SQL,如上所示。

    使用association配置还可以使用resultMap属性配置成一个已经存在的resultMap映射。 我们吧sys_role相关的映射提取出来,改造如下

    	<!-- 使用resultMap配置一对一映射  使用association -->
    	<resultMap id="roleMap"  type="com.artisan.mybatis.xml.domain.SysRole" >
    		<id  property="id" column="id"/>
    		<result property="roleName" column="role_name"/>
    		<result property="enabled" column="enabled"/>
    		<result property="createBy" column="create_by"/>
    		<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
    	</resultMap>
    	
    	<resultMap id="userRoleMap_byExtendsAndAssociation_ResultMap"  extends="userMap"
    			   type="com.artisan.mybatis.xml.domain.SysUser">
    		<association property="sysRole" columnPrefix="sysRole_"
    			javaType="com.artisan.mybatis.xml.domain.SysRole" resultMap="roleMap">
    		</association>	   
    	</resultMap>
    

    到这里,是不是没有这么麻烦了? 还有一个需要注意的地方:roleMap我们目前是写在UserMapper.xml中,更合理的应该在RoleMapper.xml中。如果真的在RoleMapper.xml中的话,,通过resultMap来引用的话,就必须要加上命名空间了。 如果不加的话,MyBatis会默认添加调用者当前命名空间的前缀。

    <resultMap id="userRoleMap_byExtendsAndAssociation_ResultMap"  extends="userMap"
    			   type="com.artisan.mybatis.xml.domain.SysUser">
    		<association property="sysRole" columnPrefix="sysRole_"
    			javaType="com.artisan.mybatis.xml.domain.SysRole" resultMap="com.artisan.mybatis.xml.mapper.RoleMapper.roleMap">
    		</association>	   
    	</resultMap>
    

    单元测试

    @Test
    	public void selectSysUserAndSysRoleById4Test() {
    		logger.info("selectSysUserAndSysRoleById4Test");
    		// 获取SqlSession
    		SqlSession sqlSession = getSqlSession();
    		try {
    			// 获取UserMapper接口
    			UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    			// 注意:数据库中id=1的用户拥有2个角色,不适合这个例子。
    			// 调用selectSysUserAndSysRoleById4方法,查询id=1001的用户及其角色
    			SysUser sysUser = userMapper.selectSysUserAndSysRoleById4(1001L);
    			// 期望用户不为空
    			Assert.assertNotNull(sysUser);
    			// 期望角色不为空
    			Assert.assertNotNull(sysUser.getSysRole());
    
    			logger.info(sysUser);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			sqlSession.close();
    			logger.info("sqlSession close successfully ");
    		}
    	}
    

    日志

    2018-05-01 01:08:18,898  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
    2018-05-01 01:08:18,905  INFO [main] (BaseMapperTest.java:29) - reader close successfully
    2018-05-01 01:08:18,913  INFO [main] (UserMapperTest.java:1083) - selectSysUserAndSysRoleById4Test
    2018-05-01 01:08:19,019 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT u.id, u.user_name , u.user_password , u.user_email , u.user_info , u.create_time , u.head_img , r.id sysRole_id, r.role_name sysRole_role_name, r.enabled sysRole_enabled, r.create_by sysRole_create_by, r.create_time sysRole_create_time FROM sys_user u INNER JOIN sys_user_role ur ON u.id = ur.user_id INNER JOIN sys_role r ON ur.role_id = r.id WHERE u.id = ? 
    2018-05-01 01:08:19,155 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1001(Long)
    2018-05-01 01:08:19,212 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, user_name, user_password, user_email, user_info, create_time, head_img, sysRole_id, sysRole_role_name, sysRole_enabled, sysRole_create_by, sysRole_create_time
    2018-05-01 01:08:19,213 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1001, artisan, 123456, test@artisan.com, <<BLOB>>, 2018-04-13 21:12:47.0, <<BLOB>>, 2, 普通用户, 1, 1, 2018-04-13 21:12:46.0
    2018-05-01 01:08:19,231 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
    2018-05-01 01:08:19,232  INFO [main] (UserMapperTest.java:1097) - SysUser [id=1001, userName=artisan, userPassword=123456, userEmail=test@artisan.com, userInfo=测试用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018, sysRole=SysRole [id=2, roleName=普通用户, enabled=1, createBy=1, createTime=Fri Apr 13 21:12:46 BOT 2018, user=null, privilegeList=null]]
    2018-05-01 01:08:19,239  INFO [main] (UserMapperTest.java:1102) - sqlSession close successfully 
    
    

    方式四:asscociation标签的嵌套查询

    前面三种方式通过负载的SQL查询获取结果,其实还可以利用简单的SQL通过多次查询转换为我们需要的结果,这种方式与根据业务逻辑手动执行多次SQL的方式很像,最后将结果组成一个对象。

    场景和情况比较复杂,后续单独阐述

    展开全文
  • 公民和公民的身份证,是一个一对一的例子,一个公民只有一个身份证。 这个是基于主键的,基于外键的映射在:http://blog.csdn.net/nthack5730/article/details/45336457 场景准备: 实体类:Person.java、...

    背景:

    公民和公民的身份证,是一个一对一的例子,一个公民只有一个身份证。


    这个是基于主键的,基于外键的映射在:http://blog.csdn.net/nthack5730/article/details/45336457


    场景准备:

    实体类:Person.java、IdCard.java



    Person.java

    package h_hbm_oneToOne2;
    
    public class Person {
    	private Integer id;
    	private String name;
    	
    	private IdCard idCard;//关联的身份证
    
    	public Integer getId() {
    		return id;
    	}
    
    	public void setId(Integer id) {
    		this.id = id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public IdCard getIdCard() {
    		return idCard;
    	}
    
    	public void setIdCard(IdCard idCard) {
    		this.idCard = idCard;
    	}
    	
    }
    



    IdCard.java

    package h_hbm_oneToOne2;
    
    public class IdCard {
    	private Integer id;
    	private String number;
    	
    	private Person person;//不要初始化,初始化会使对象处于临时状态,会使保存的时候抛异常,关联的人的对象
    
    	public Integer getId() {
    		return id;
    	}
    
    	public void setId(Integer id) {
    		this.id = id;
    	}
    
    	public String getNumber() {
    		return number;
    	}
    
    	public void setNumber(String number) {
    		this.number = number;
    	}
    
    	public Person getPerson() {
    		return person;
    	}
    
    	public void setPerson(Person person) {
    		this.person = person;
    	}
    	
    	
    }
    




    IdCard.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                                       "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!-- This mapping demonstrates -->
    <!-- 告诉hibernate需要找哪个表 -->
    <hibernate-mapping package="h_hbm_oneToOne2">
    
    	<!-- User表对应的映射关系 -->
    	<class name="IdCard" table="idCard">
    		<id name="id">
    			<generator class="native" />
    		</id>
    		<property column="number" name="number" type="string" />
    		
    		<!-- 
    			person属性:Person类型
    			表达的是本类与IdCard的一对一关系
    			采用基于主键的一对一映射的方式
    			本方无外键方
    			property-ref:写的是对方映射中外键列对应的属性名,也就是Person类下的idCard属性名
    		-->
    		<one-to-one name="person" class="Person"/>
    				
    	</class>
    </hibernate-mapping>
    




    Person.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                                       "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!-- This mapping demonstrates -->
    <!-- 告诉hibernate需要找哪个表 -->
    <hibernate-mapping package="h_hbm_oneToOne2">
    
    	<!-- User表对应的映射关系 -->
    	<class name="Person" table="person">
    		<id name="id">
    			<!-- 
    				当使用基于主键的一对一映射时,有外键方的主键生成策略一定要是foreign 
    				参数property:生成主键值时所根据的对象【一对一时关联的对方】
    			-->
    			<generator class="foreign">
    				<param name="property">idCard</param>
    			</generator>
    			
    		</id>
    		<property column="name" name="name" type="string" />
    		
    		<!-- 
    			IdCard属性:IdCard类型
    			表达的是本类与IdCard的一对一关系
    			采用基于主键的一对一映射的方式
    			本方有外键
    		-->
    		<one-to-one name="idCard" class="IdCard" constrained="true"></one-to-one>
    		
    				
    	</class>
    </hibernate-mapping>
    



    测试代码:

    App.java

    package h_hbm_oneToOne2;
    
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.junit.Test;
    
    import cn.marer.model.HibernateUtils;
    
    public class APP {
    	private static SessionFactory sessionfactory = HibernateUtils.getSessionFactory();
    	
    	@Test
    	public void testSave(){
    		Session session = sessionfactory.openSession();
    		
    		//开启事务
    		session.beginTransaction();
    		
    		//构建对象
    		Person person = new Person();
    		person.setName("张三");
    		
    		IdCard id = new IdCard();
    		id.setNumber("123456");
    		person.setIdCard(id);
    		
    //		session.save(id);
    		session.save(person);
    		
    		//提交事务
    		session.getTransaction().commit();
    		session.close();
    	}
    	
    	
    	@Test
    	public void testGet(){
    		Session session = sessionfactory.openSession();
    		
    		//开启事务
    		session.beginTransaction();
    		
    		//获取一方
    //		Person person= (Person) session.get(Person.class, 1);
    //		System.out.println(person.getName()+"---->" + person.getIdCard());
    		
    		
    		IdCard id = (IdCard) session.get(IdCard.class, 1);
    		System.out.println(id.getNumber() + "---->" + id.getPerson().getName());
    		
    		
    		
    		//提交事务
    		session.getTransaction().commit();
    		session.close();
    	}
    	
    	
    	// 解除关联关系
    	@Test
    	public void testRemoveRelation(){
    		Session session = sessionfactory.openSession();
    		
    		// 开启事务
    		session.beginTransaction();
    		
    		// 从无外键方解除关联关系不可以
    		IdCard id = (IdCard) session.get(IdCard.class, 1);
    		id.setPerson(null);
    		
    		
    		// 基于主键的一对一映射,从有外键方解除关联关系,不可以。因为主键不能为空。
    //		Person person = (Person) session.get(Person.class, 1);
    //		person.setIdCard(null);
    		
    		
    		
    		//提交事务
    		session.getTransaction().commit();
    		session.close();
    	}
    	
    	
    	// 删除对对方的影响
    	@Test
    	public void testDelte(){
    		Session session = sessionfactory.openSession();
    		
    		// 开启事务
    		session.beginTransaction();
    		
    		// 会报异常
    //		IdCard id = (IdCard) session.get(IdCard.class, 1);
    //		session.delete(id);
    		
    		// 如果没有关联的对方,能删除
    		// 如果有关联的对方:因为会直接执行删除自己,所以无外键方会有异常,有外键方没有异常。
    		Person person = (Person) session.get(Person.class, 1);
    		session.delete(person);
    		
    		// 有外键方能维护关联关系,从无外键方不能维护关联关系
    		
    		//提交事务
    		session.getTransaction().commit();
    		session.close();
    	}
    }
    














    展开全文
  • 一、mybatis 一对一映射关系 1.一对一映射关系 什么是一对一映射关系?:从数据库的角度出发就是在任意一个表中引入另外一个表的主键作为外键。在本类的定义中定义另外一个类的对象。 在mybatis中,我们通过.

    ------------------------------------------------原创不易,如若喜欢,请点一点赞吧!---------------------------------------------

    通过前几篇文章的学习,我们已经大致了解了mybatis基础知识,并可以使用基础的sql语句来操作数据库。在关系型数据库中,表与表之间存在着一对一,一对多,多对多这几种映射关系。映射关系是mybatis的核心知识,在以后的工作中,我们会经常遇到以上几种映射关系,因此,我们很有必要学好映射关系。

    一、mybatis 一对一映射关系

    1.一对一映射关系

    • 什么是一对一映射关系?:从数据库的角度出发就是在任意一个表中引入另外一个表的主键作为外键。在本类的定义中定义另外一个类的对象。
    • 在mybatis中,我们通过resultMap元素的子元素 association来进行处理。
    • association元素具有以下配置属性
    属性名称作用
    property指定映射到的实体类对象属性,与表字段一一对应
    column指定表中对应的字段
    select指定引入嵌套查询的子SQL 语句,该属性用于关联映射中的嵌套查询。
    javaType指定映射到实体对象属性的类型
    • 在mybatis中设定了两种查询方式:嵌套查询及嵌套结果查询方式
     <!--方式一:嵌套查询--!〉
            <association property="card" column="card_id" javaType="com.itheima.po.ldCard"
            select="com.itheima.mapper.ldCardMapper.findCodeByld" />
    
            <!--方式二:嵌套结果--!〉
            <association property="card" javaType="com.itheima.po.ldCard">
                <id property="id" column="card_id" />
                <result property="code" column="code" />
            </association>
    

    2.【案例分析】

    案例描述: 个人和身份证之间是一对一的关系,以个人信息和个人身份证一对一关系为例,查询个人信息,通过一对一映射关系来获取对应身份证信息。
    【分析】: 根据mybatis框架我们可知,mybatis关系映射语句都是在Mapper.xml中书写的,在mybatis关系映射中,我们需要用到 resuletMap 元素,该元素的用法在上一篇文章中resultMap映射详解进行过讲解,可自行查阅。StudentMapper.xml 的写法如下

    映射文件代码:StudentMapper.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 3-5行是mybatis约束配置 -->
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.mybatis.mapper.StudentMapper">
    	<!-- 嵌套查询 
    	<select id="querystudent" parameterType="int" resultMap="IdS">
    		select * from student where id=#{id}
    	</select>
    	<resultMap type="Student" id="IdS">
    		<id property="id" column="id"/>
    		<result property="s_name" column="s_name"/>
    		<result property="s_age" column="s_age"/>
    		<result property="s_sex" column="s_sex"/>
    		<association property="card_id" column="card_id" javaType="Idcard"
    			select="org.mybatis.mapper.IdcardMapper.queryinfo">
    		</association>
    	</resultMap>
    	-->
    	<!--  嵌套结果-->
    	<select id="querystudent" resultMap="Ids"> 	<!-- select语句的返回值是resultMap类型-->
    		<!-- sql查询语句, 当p.card_id = idcard.id时,获取student表中所有数据和idcard表中的code数据-->
    		select p.*,idcard.code 
    		from student p,idcard idcard
    		where p.card_id = idcard.id
    	</select>
    		<!-- 一对一映射需要使用resultMap元素封装查询到的信息,id值需要与上文select语句中引用的resultMap="Ins"值相同--->
    	<resultMap type="Student" id="Ids">
    	<!--映射 Student类中属性与student表的字段一一对应-->
    		<id property="id" column="id"/>
    		<result property="s_name" column="s_name"/>
    		<result property="s_age" column="s_age"/>
    		<result property="s_sex" column="s_sex"/>
    		<!--映射 Idcard类中属性与idcard表的字段一一对应,并将数据放入Student类的属性card_id中-->
    		<association property="card_id" javaType="Idcard">
    			<id property="id" column="card_id"/>
    			<result property="code" column="code"/>
    		</association>
    	</resultMap>
    </mapper>
    

    二、mybatis 一对多映射关系

    1.一对多映射关系

    • 什么是一对多关系:一对多关系就是表A中一条数据对应表B中的多条数据,例如,用户和订单之间的关系,一个用户可以有多个订单信息。

    • 在mybatis中,我们通过resultMap元素的子元素 collection来进行处理。

    • collection元素具有以下配置属性

    属性名称作用
    property指定映射到的实体类对象属性,与表字段一一对应
    column指定表中对应的字段
    select指定引入嵌套查询的子SQL 语句,该属性用于关联映射中的嵌套查询。
    javaType指定映射到实体对象属性的类型
    ofTypeofType 属性与javaType 属性对应,它用于指定实体对象中集合类属性所包含的元素类型。
    • 需要注意的是:在一对多映射和多对多映射中,collection 元素属行中使用的是ofType属性来指定实体对象,而不是使用JavaType属性。

    2.【案例分析】

    案例描述: 以用户和订单为例,若一个用户有用三个订单,则如何通过查询用户来获取用户对应的订单信息。
    【分析】: 一个用户可以有多个订单信息。这就构成了一对多的映射关系。通过mybatis中的一对多映射关系,在mapper.xml文件中写入对应语句后则可完成该需求。

    映射文件代码:OrdersMapper.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">
    <!--a.一对多嵌套结果  -->
    <mapper namespace="org.mybatis.mapper.UserMapper">
    	<select id="queryorders" parameterType="int" resultMap="Ins">        <!-- select语句的返回值是resultMap类型-->
    		<!-- sql查询语句, 当u.id = o.user_id, u.id="传入值"时,获取user 表中id="传入值"的数据以及orders 表中的订单数据-->
    		select u.*,o.id as orders_id,o.number
    		from user u,orders o
    		where u.id = o.user_id
    		and u.id=#{id}
    	</select>
    	<!-- 一对多映射需要使用resultMap元素封装查询到的信息,且id值需要与上文select语句中引用的resultMap="Ins"值相同-->
    	<resultMap type="org.mybatis.beans.User" id="Ins">
    		<!--映射 User类中属性与user表的字段一一对应-->
    		<id property="id" column="id"/>
    		<result property="username" column="username"/>
    		<result property="address" column="address"/>
    		  <!--  a.1对多关联映射: collection  
    			ofType 表示属性集合中元素的类型, List<Orders>属性即 Orders 类-->
    		<collection property="orderList" ofType="org.mybatis.beans.Orders">
    		<!--映射 Orders类中属性与orders表的字段一一对应-->
    		<id property="id" column="orders_id"/>
    		<result property="number" column="number"/>
    		</collection>
    	</resultMap>
    </mapper>
    

    三、mybatis 多对多映射关系

    1.多对多映射关系

    • 什么是多对多关系: 一对多关系就是表A中一条数据对应表B中的多条数据,例如,用户和订单之间的关系,一个用户可以有多个订单信息。
    • 在mybatis中,与一对多映射一致,我们通过resultMap元素的子元素 collection来进行处理。这里就不再多collection元素属性与上文一致。
      • 需要注意的是:在一对多映射和多对多映射中,collection 元素属行中使用的是ofType属性来指定实体对象,而不是使用JavaType属性。

    2.【案例分析】

    案例描述: 以订单和商品为例,若一个订单有用三个商品,一个商品有五个不同的订单,则如何通过查询订单来获取对应的商品信息,如何通过查询商品来获取对应的订单信息。
    【分析】: 一个商品可以有多个订单信息。一个订单可以有多个商品信息。这就构成了多对多的映射关系。一般来说,在多对多的映射中,会通过生成中间表的方式来处理,通过一个中间表保存订单信息和商品信息。但Mapper.xml中的resultMap 元素的写法与一对多基本一致。

    映射文件代码:OrdersMapper.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="org.mybatis.mapper.OrdersMapper">
    <!-- 多对多嵌套结果 	-->
    	<select id="queryproduct" parameterType="int" resultMap="Ins">
    		select o.*,p.id as pid,p.name,p.price
    		from orders o,product p,ordersitem oi
    		where oi.orders_id=o.id
    		and oi.product_id=p.id
    		and o.id=#{id}
    	</select>
    	<resultMap type="Orders" id="Ins">
    		<id property="id" column="id"/>
    		<result property="number" column="number"/>
    		<collection property="productList" ofType="Product">
    			<id property="id" column="pid"/>
    			<result property="name" column="name"/>
    			<result property="price" column="price"/>
    		</collection>
    	</resultMap>
    
    </mapper>
    

    ---------------------------------------------------------------------------------------------------公众号内有更多干货。欢迎关注!

    在这里插入图片描述

    展开全文
  • 当我们学习heribnate的时候,也就是SSH框架的网上商城的时候,我们就学习过它对应的高级映射,一对一映射,一对多映射,多对多映射。对于SSM的Mybatis来说,肯定也是差不多的。既然开了头了,我们就也来简单说一些...
  • 一对一映射几乎涉及了所有可以使用的映射方式:共享主键、外键和关联表。每一种方式都有相对特定的使用场合。而与此同时,one-to-one关系的 lazy loading总是一个让人非常疑惑的问题,下文在介绍每一种一对一映射...
  • 其实一对一和一对多映射,在前面的配置中已经接触到,我没在日志里直接说明,是因为想要在之后写一篇总结日志(就是本篇),总结这些高级映射的配置。例如一对一查询在关联的嵌套结果集查询中就涉及到,一对多查询则...
  • 在Hibernate中实现一对一映射,有两种实现方式:1、主键关联;2、唯一外键关联,这里先说一下主键关联映射。  主键关联映射:其中一个表的主键依赖于另一张表的主键而建立起的一对一的关系,这两张互相关联的表的...
  • 在实际开发中我们不可能只是对单表进行操作,必然要操作多表,本文就来讲解多表操作中的一对一关联映射和一对多(或多对一)关联映射,至于多对多关联映射实质上也是两个一对多(或多对一)关联映射,所以在这里我并不...
  • 实例背景:公民和公民的身份证,是一个一对一的例子,一个公民只有一个身份证。以这个背景开展说明!
  • Django一对一 多对多 一对多
  • private List<Orders> list ; public List<Orders> getList() { return list; } public void setList(List<Orders> list) { this.list = list; }
  • 本例模仿用户与身份证相对应的关系,即一个用户对应一个身份证信息,且身份证信息不能重复,下面代码是实现基于外键的一对一映射 1.hibernate.cfg.xml <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/...
  • mybatis的一对映射collection

    千次阅读 2020-10-28 09:32:46
    简单映射一对一) 一对多映射 方式1:按照查询嵌套处理 方式2:按照结果嵌套处理 简单映射一对一) mybatis结果集映射ResultMap 一对多映射 我们有2个类,一个班级类ClassRoom,一个学生类...
  • 一对一(resultType实现方式) 我们这里就利用订单和用户模型,从订单角度出发,一个订单只能给一个用户创建,所以是一对一,但是从用户角度出发,一个用户是可以创建多个订单的,所以是一对多。但是我们这里从订单...
  • 两个实体对象之间是一对一的关联映射,即一个对象只能与另外唯一的一个对象相对应。例如:一个人(Person)只有一张身份证(IdCard)。
  • mybatis 一对一映射(两种方式)

    万次阅读 2015-08-05 20:25:22
    对于一对一的关系映射一共有两种解决方案: 开发步骤:1)写OrdersMapperUser.xml文件 2)编写与xml同名的接口OrdersMapperUser 3)测试 声明:一下xml文件的代码都在中 方式一:使用包装类完成映射关系(比较容易...
  • Mybatis之高级映射一对映射

    千次阅读 2018-09-12 18:07:37
    当然resultType也能实现,需要将所查询的信息定义到一个pojo(详情见一对一映射中的resultType),这里讲的是resultMap。 需求:查询人员、部门信息并关联查询其父级部门信息。 随意定义数据库的三张表: 人员表: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,554,839
精华内容 621,935
关键字:

一对一的映射