MyBatis学习二

接着上一个学习做,内容比较多,resultMap,一对多,多对一


别名

在mybaits-conf.xml,加入如下代码即可将包中的内容变成别名,别名可以在resultType中使用

<typeAliases>
     <package name="cn.hd.po" />
</typeAliases>
别名在Spring中的配置是sqlSessionFactory中的

<!-- 自动扫描mapping.xml文件 -->  
<property name="mapperLocations" value="classpath:com/test/mapping/*.xml"></property>  

resultMap

如果查询出来的结果和表数据一样,就没有必要用到resultMap。但有时候会出现页面显示比表中数据多。比如年龄。比如多表查询。

我这里就用多表查询算了,用一个一对一的数据做个resultMap的试验了。

加入了2个表,后面一对多和多对一都可以用

create table T_DEPT
(
  DID   NUMBER not null,
  DEPT_NAME VARCHAR2(20),
  PID   NUMBER
);
create table T_U_JOB
(
  JID NUMBER not null,
  USER_ID NUMBER not null,
  JOB_NAME VARCHAR2(20) not null
)
部门和工作,一个人可以有多个任职,一个人只能一个部门。

package cn.hd.vo;

import cn.hd.po.User;

public class UserVo extends User {
	private String deptName;
	private String jobName;
	public String getDeptName() {
		return deptName;
	}
	public void setDeptName(String deptName) {
		this.deptName = deptName;
	}
	public String getJobName() {
		return jobName;
	}
	public void setJobName(String jobName) {
		this.jobName = jobName;
	}
}
一个vo,值对象,好了,现在就是重头戏了,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="cn.hd.dao.UserMapper">
<span style="white-space:pre">	</span><!-- ++++++++多表查询+++++++++++++多表查询++++++++++++++多表查询++++++++++++ -->
<span style="white-space:pre">	</span><resultMap type="cn.hd.vo.UserVo" id="userResultMap">
 <span style="white-space:pre">		</span><!-- 返回值主键,并不是数据库主键 -->
       <id column="id" property="userid" />
       <!-- column是结果集的列名,并不是字段名称,property是返回对象中的字段名称 -->
       <result column="dept_name" property="deptName"/>
       <result column="depid" property="jobName" />
    </resultMap>
<span style="white-space:pre">	</span><!-- 使用resultType查询,所以这里需要使用别名讲字段名称改为和对象中的一致 -->
<span style="white-space:pre">	</span><select id="queryVo" resultType="cn.hd.vo.UserVo">
     <span style="white-space:pre">	</span>select u.*,d.dept_name as deptName from t_user u,t_dept d where u.did=d.did
    </select>
    <!-- 因为resultMap中已经映射的了字段名称,所以这里不需要别名 -->
<span style="white-space:pre">	</span><select id="queryResultMap" resultMap="userResultMap">
     <span style="white-space:pre">	</span>select u.*,d.dept_name from t_user u,t_dept d where u.did=d.did
    </select>
<span style="white-space:pre">	</span><!-- ++++++++基本查询+++++++++++++基本查询++++++++++++++基本查询++++++++++++ -->
    <!--根据id查询得到一个user对象  List<Userbean>-->
     <select id="queryAll" resultType="cn.hd.po.User">
     <span style="white-space:pre">	</span>select * from t_user
     </select>
     
     <select id="findById" parameterType="int" resultType="cn.hd.po.User">
     <span style="white-space:pre">	</span><!-- 只有一个参数时,#{这里可以随便写} -->
        select  *  from t_user where userid=#{vlues}
     </select>
   
</mapper>

测试代码加入如下,这里引入了一个jar包fastjson-1.1.41.jar,用于输出对象。

	@Test
	public void testFindVo() {
        List<UserVo> user=session.selectList("cn.hd.dao.UserMapper.queryVo");
        for(UserVo u :user)
        {
        	System.out.println(JSON.toJSONString(u));
        }
	}
	@Test
	public void testFindResultMap() {
        List<UserVo> user=session.selectList("cn.hd.dao.UserMapper.queryResultMap");
        for(UserVo u :user)
        {
        	System.out.println(JSON.toJSONString(u));
        }
	}

2个结果都是输出了这个结果,那么搞定了。

{"deptName":"信息部","did":1,"jid":1,"password":"123","realname":"张飞","userid":1,"username":"张三"}
{"deptName":"教务部","did":2,"jid":2,"password":"321","realname":"李世民","userid":2,"username":"李四"}

总结,resultType是使用的现有的对象,resultMap是需要定义一个userResultMap,在这个map中人为去干涉字段映射。

resultType是使用约定,resultMap使用配置。约定规范,配置灵活。

resultMap的配置可以比使用的多,也可以少。多的字段不会启用,少的配置相应的字段数据会丢失,如果字段名称配置错误了,数据也会丢失。(这里并没有报错!!!)

一对多,多对一

一对一的上面已经写过了,现在看一对多,多对一。我就直接用resultType了,resultMap还需要配置collection 。算了一起写吧!好好学习,天天向上。
事实证明偷的懒始终是需要补回来的,上面偷懒没有写po,现在补上呗。
package cn.hd.po;

public class Job {
	private Long jid;
	private Long userId;
	private String jobName;
	
	public Long getJid() {
		return jid;
	}
	public void setJid(Long jid) {
		this.jid = jid;
	}
	public String getJobName() {
		return jobName;
	}
	public void setJobName(String jobName) {
		this.jobName = jobName;
	}
	public Long getUserId() {
		return userId;
	}
	public void setUserId(Long userId) {
		this.userId = userId;
	}
	
}
package cn.hd.po;

public class Dept {
	private Long deptId;
	private String deptName;
	private Long pid;
	
	public Long getDeptId() {
		return deptId;
	}
	public void setDeptId(Long deptId) {
		this.deptId = deptId;
	}
	public String getDeptName() {
		return deptName;
	}
	public void setDeptName(String deptName) {
		this.deptName = deptName;
	}
	public Long getPid() {
		return pid;
	}
	public void setPid(Long pid) {
		this.pid = pid;
	}
}
package cn.hd.vo;

import java.util.List;

import cn.hd.po.Dept;
import cn.hd.po.Job;
import cn.hd.po.User;

public class UserVoO2M extends User {
	private Dept dept;
	private List<Job> listJob;
	
	public Dept getDept() {
		return dept;
	}
	public void setDept(Dept dept) {
		this.dept = dept;
	}
	public List<Job> getListJob() {
		return listJob;
	}
	public void setListJob(List<Job> listJob) {
		this.listJob = listJob;
	}
	
}
ok,现在几个java文件就做完成了。mapper中就一个接口,就不贴出来了,没必要了。新增一个xml叫UserMapperO2M.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="cn.hd.dao.UserMapperO2M">

	<!-- ++++++一对多,多对一+++++++++++++++一对多,多对一+++++++++++++++一对多,多对一+++++++ -->
	<resultMap type="cn.hd.vo.UserVoO2M" id="userO2M">
 		<!-- 返回值主键,并不是数据库主键-->
       <id column="userid" property="userid" />
       <result column="username" property="username"/>
       <!-- 这个其实省略了很多字段,因为使用约定,所以就不写了    非常奇怪,这里使用了association之后就不适用约定了-->
       
       <!-- 一对一 property中对应到成员变量    javaType是类型-->
       <association property="dept" javaType="cn.hd.po.Dept">
       		<id column="did" property="deptId"/>
            <result column="dept_name" property="deptName"/>
       </association>  
       <!-- 1对多使用collection  property对应到1的成员变量  ofType是成员变量的范型   -->
       <collection property="listJob" ofType="cn.hd.po.Job">
       		<id column="jobid" property="jid"/>
       		<result column="user_id" property="userId"/>
            <result column="job_name" property="jobName"/>
       </collection>
    </resultMap>
	<!-- 使用resultType查询,所以这里需要使用别名讲字段名称改为和对象中的一致 -->
	<select id="queryVo" resultMap="userO2M">
     	select u.*,j.jid as jobid,j.user_id,j.job_name from t_user u,t_u_job j where u.userid = j.user_id
    </select>
   
</mapper>
然后测试类和执行结果
package cn.hd.test;

import java.util.List;

import org.junit.Test;

import com.alibaba.fastjson.JSON;

import cn.hd.vo.UserVoO2M;

public class TestMyBatisO2M extends Junit{
	@Test
	public void testFindVo() {
        List<UserVoO2M> user=session.selectList("cn.hd.dao.UserMapperO2M.queryVo");
        for(UserVoO2M u :user)
        {
        	System.out.println(JSON.toJSONString(u));
        }
	}
}
{"did":0,"jid":0,"listJob":[{"jid":1,"jobName":"会长","userId":2},{"jid":2,"jobName":"主席","userId":2},{"jid":3,"jobName":"皇帝","userId":2}],"userid":2,"username":"李四"}
{"did":0,"jid":0,"listJob":[{"jid":4,"jobName":"战士","userId":1},{"jid":5,"jobName":"大将军","userId":1},{"jid":6,"jobName":"狮子吼","userId":1}],"userid":1,"username":"张三"}

好,现在结果对了,但是这里的约定没有生效,User对象中的很多字段都没有写入进去,好奇怪,回头在研究了。

遇到的问题:
1、首先是一个,“Error querying database.  Cause: java.sql.SQLException: ORA-00911: 无效字符”,这个问题太坑,我开始以为是字段错了,找了半天,后来才发现原来吧分号复制进去了。去掉分号就正常了。
2、第二个就是约定不生效的问题。一定要写result的配置。尚未解决。
3、第三个就是字段名称一样,导致数据错误,我user中有一个jid,t_u_job中也有一个jid。


然后结果就变成这样了。
{"dept":{"deptId":2,"deptName":"教务部"},"did":0,"jid":0,"listJob":[{"jid":2,"jobName":"会长","userId":2}],"userid":2,"username":"李四"}
{"dept":{"deptId":1,"deptName":"信息部"},"did":0,"jid":0,"listJob":[{"jid":1,"jobName":"战士","userId":1}],"userid":1,"username":"张三"}
明显可以看到listJob中少了好几条数据就是因为Jid重复的问题。我这里将Jid写了个别名了。

4、我发现一个好玩的东西,就是在包下,同名的select id,是有关系的,应该是使用了接口代理的原因吧!我说下表现。
大家可以发现我在UserMapper.xml中有一个queryVo  ,在UserMapperO2M.xml 也有一个queryVo  。好,这个是吧UserMapper.xml中queryVo改一下
<select id="queryVo" resultType="cn.hd.vo.UserVo">
     	select u.*,d.dname as deptName from t_user u,t_dept d where u.did=d.did
</select>
好,那么这个是去测试UserMapperO2M.xml中的queryVo方法,“Error querying database.  Cause: java.sql.SQLException: ORA-00904: "D"."DNAME": 标识符无效”。
其实UserMapperO2M中的方法明显是对的,但是这里还是出错了。
后面一直重现不了,看来还是没找对原因。


总结:
半自动化配置,配置数据库与JAVA类的映射。
一对多时,一对一时 在id标签中的是确定对象是否重复的关键。如果id不重复,那么就会被认为是1对多种的1。

association 一对一
collection 一对多



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值