mybatis3.0添加了association和collection标签专门用于对多个相关实体类数据进行级联查询,但仍不支持多个相关实体类数据的级联保存和级联删除操作。因此在进行实体类多对多映射表设计时,需要专门建立一个关联对象类对相关实体类的关联关系进行描述。下文将以“User”和“Group"两个实体类之间的多对多关联映射为例进行CRUD操作。
建立user表,对应实体类"User",建表语句如下:
<!--StartFragment-->
- CREATETABLE`user`(
- `id`int(11)NOTNULLauto_increment,
- `name`varchar(40)collateutf8_unicode_cidefaultNULL,
- `password`varchar(20)collateutf8_unicode_cidefaultNULL,
- `createtime`timestampNULLdefaultCURRENT_TIMESTAMP,
- PRIMARYKEY(`id`)
- )
建立group_info表,对应实体类"Group",建表语句如下:
- CREATETABLE`group_info`(
- `id`int(11)NOTNULLauto_increment,
- `name`varchar(40)collateutf8_unicode_cidefaultNULL,
- `createdate`timestampNULLdefaultCURRENT_TIMESTAMP,
- `state`int(1)default'0'COMMENT'0:可见;1:不可见',
- PRIMARYKEY(`id`)
- )
建立user_group表,对应实体类"UserGroupLink"(该类为User和Group两个实体类之间的关系描述),建表语句如下:
- CREATETABLE`user_group`(
- `user_id`int(11)defaultNULL,
- `group_id`int(11)defaultNULL,
- `createdate`timestampNULLdefaultCURRENT_TIMESTAMP,
- KEY`FK_user_group_user_id`(`user_id`),
- KEY`FK_user_group_group_id`(`group_id`),
- CONSTRAINT`FK_user_group_group_id`FOREIGNKEY(`group_id`)REFERENCES`group_info`(`id`),
- CONSTRAINT`FK_user_group_user_id`FOREIGNKEY(`user_id`)REFERENCES`user`(`id`)
- )
建立实体类User,代码如下:
- packagecom.xxt.ibatis.dbcp.domain;
- importjava.util.Date;
- importjava.util.List;
- /**
- *@describe:User实体类
- *@author:Nirvana
- *@version:V1.02011-3-11下午06:06:49create
- */
- publicclassUser{
- privatelongid;
- privateStringname;
- privateStringpassword;
- privateDatecreateTime;
- privateList<Group>group;
- publicDategetCreateTime(){
- returncreateTime;
- }
- publicvoidsetCreateTime(DatecreateTime){
- this.createTime=createTime;
- }
- publiclonggetId(){
- returnid;
- }
- publicvoidsetId(longid){
- this.id=id;
- }
- publicStringgetName(){
- returnname;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- publicStringgetPassword(){
- returnpassword;
- }
- publicvoidsetPassword(Stringpassword){
- this.password=password;
- }
- publicList<Group>getGroup(){
- returngroup;
- }
- publicvoidsetGroup(List<Group>group){
- this.group=group;
- }
- }
建立实体类Group,代码如下:
- packagecom.xxt.ibatis.dbcp.domain;
- importjava.util.Date;
- importjava.util.List;
- /**
- *@describe:Group实体类
- *@author:Nirvana
- *@version:V1.02011-3-7下午08:10:29create
- */
- publicclassGroup{
- privatelongid;
- privateStringname;//组名
- privateDatecreateTime;
- privateintstate;//0可见状态1不可见状态
- privateList<User>user;
- publicDategetCreateTime(){
- returncreateTime;
- }
- publicvoidsetCreateTime(DatecreateTime){
- this.createTime=createTime;
- }
- publiclonggetId(){
- returnid;
- }
- publicvoidsetId(longid){
- this.id=id;
- }
- publicStringgetName(){
- returnname;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- publicintgetState(){
- returnstate;
- }
- publicvoidsetState(intstate){
- this.state=state;
- }
- publicList<User>getUser(){
- returnuser;
- }
- publicvoidsetUser(List<User>user){
- this.user=user;
- }
- }
建立实体类UserGroupLink,用于描述User和Group之间的对应关系,代码如下:
- packagecom.xxt.ibatis.dbcp.domain;
- importjava.util.Date;
- /**
- *@describe:描述User和Group之间的映射关系
- *@author:Nirvana
- *@version:V1.02011-3-11下午02:57:52create
- */
- publicclassUserGroupLink{
- privateUseruser;
- privateGroupgroup;
- privateDatecreateTime;
- publicDategetCreateTime(){
- returncreateTime;
- }
- publicvoidsetCreateTime(DatecreateTime){
- this.createTime=createTime;
- }
- publicGroupgetGroup(){
- returngroup;
- }
- publicvoidsetGroup(Groupgroup){
- this.group=group;
- }
- publicUsergetUser(){
- returnuser;
- }
- publicvoidsetUser(Useruser){
- this.user=user;
- }
- }
建立user实体类的映射文件user.map.xml,代码如下:
- <?xmlversion="1.0"encoding="UTF-8"?>
- <!DOCTYPEmapper
- PUBLIC"-//mybatis.org//DTDMapper3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mappernamespace="com.xxt.ibatis.dbcp.domain.User">
- <resultMaptype="User"id="userMap">
- <idproperty="id"column="id"/>
- <resultproperty="name"column="name"/>
- <resultproperty="password"column="password"/>
- <resultproperty="createTime"column="createtime"/>
- </resultMap>
- <resultMaptype="User"id="userGroupMap"extends="userMap">
- <collectionproperty="groups"ofType="Group">
- <idproperty="id"column="goupId"/>
- <resultproperty="name"column="groupName"/>
- <resultproperty="state"column="state"/>
- <resultproperty="createTime"column="groupCreateTime"/>
- </collection>
- </resultMap>
- <!--根据user表中的id查询用户信息-->
- <selectid="selectUser"parameterType="long"resultMap="userMap">
- select*fromuserwhereid=#{id}
- </select>
- <!--根据user表中的id查询用户和组信息-->
- <selectid="selectUserGroup"parameterType="long"
- resultMap="userGroupMap">
- selectu.id,u.name,u.password,u.createtime,gi.idas
- goupId,gi.nameasgroupName,gi.createdateasgroupCreateTime,
- gi.statefromuseruleftjoinuser_groupugonu.id=ug.user_id
- leftjoingroup_infogionug.group_id=gi.idwhereu.id=#{id}
- </select>
- <!--插入用户信息-->
- <insertid="saveUser"parameterType="User"keyProperty="id"
- useGeneratedKeys="true">
- insertintouser(name,password)values(#{name},#{password})
- </insert>
- <!--保存用户和组之间的关系信息-->
- <insertid="saveRelativity"parameterType="UserGroupLink">
- insertintouser_group(user_id,group_id)
- values(#{user.id},#{group.id})
- </insert>
- <selectid="selectAllUser"resultMap="userMap">
- select*fromuser
- </select>
- </mapper>
建立group实体类的映射文件group.map.xml,代码如下:
- <?xmlversion="1.0"encoding="UTF-8"?>
- <!DOCTYPEmapper
- PUBLIC"-//mybatis.org//DTDMapper3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mappernamespace="com.xxt.ibatis.dbcp.domain.Group">
- <resultMaptype="Group"id="groupMap">
- <idproperty="id"column="id"/>
- <resultproperty="name"column="name"/>
- <resultproperty="createTime"column="createdate"/>
- </resultMap>
- <resultMaptype="Group"id="groupUserMap"extends="groupMap">
- <collectionproperty="users"ofType="User">
- <idproperty="id"column="userId"/>
- <resultproperty="name"column="userName"/>
- <resultproperty="password"column="password"/>
- <resultproperty="createTime"column="userCreateTime"/>
- </collection>
- </resultMap>
- <!--根据Group表中的id或name查询组信息和组内用户信息-->
- <selectid="selectGroupUser"parameterType="Group"
- resultMap="groupUserMap">
- selectu.idasuserId,u.nameasuserName,
- u.password,u.createtimeasuserCreateTime,
- gi.id,gi.name,gi.createdate,gi.statefromgroup_infogileft
- joinuser_groupugongi.id=ug.group_idleftjoinuseruon
- uug.user_id=u.id
- <where>
- <!--当id为初始值0,不再使用id作为查询条件-->
- <iftest="id!=0">gi.id=#{id}</if>
- <!--当name为空或为空串时,不再使用name作为查询条件-->
- <iftest="name!=nullandname!=''">
- orgi.name=#{name}
- </if>
- </where>
- </select>
- <!--根据id查询group组信息-->
- <selectid="selectGroup"parameterType="Date"
- resultMap="groupMap">
- select*fromgroup_infowhereid=#{group_id}
- </select>
- <!--根据name查询group组信息-->
- <selectid="getGroupByName"parameterType="String"
- resultMap="groupMap">
- select*fromgroup_infowherename=#{name}
- </select>
- <!--插入组信息-->
- <insertid="saveGroup"parameterType="Group"keyProperty="id"
- useGeneratedKeys="true">
- insertintogroup_info(name)values(#{name})
- </insert>
- <!--删除组与组内成员之间的对应关系-->
- <deleteid="deleteGroupUser"parameterType="UserGroupLink">
- deletefromuser_group
- <where>
- <iftest="user.id!=0">user_id=#{user.id}</if>
- <iftest="group.id!=0">andgroup_id=#{group.id}</if>
- </where>
- </delete>
- <!--根据组id或者组name删除组信息-->
- <deleteid="deleteGroup"parameterType="Group">
- deletefromgroup_info
- <where>
- <iftest="id!=0">id=#{id}</if>
- <iftest="name!=null||name!=''">andname=#{name}</if>
- </where>
- </delete>
- <!--更新根据组id或者组name更新组状态-->
- <updateid="updateGroupState"parameterType="Group">
- updategroup_infosetstate=#{state}
- <where>
- <iftest="id!=0">id=#{id}</if>
- <iftest="name!=null||name!=''">andname=#{name}</if>
- </where>
- </update>
- </mapper>
建立ibatis总配置文件salMapConfig.xml,代码如下:
- <?xmlversion="1.0"encoding="UTF-8"?>
- <!DOCTYPEconfiguration
- PUBLIC"-//mybatis.org//DTDConfig3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <propertiesresource="jdbc.properties"/>
- <typeAliases>
- <typeAliastype="com.xxt.ibatis.dbcp.domain.User"alias="User"/>
- <typeAliastype="com.xxt.ibatis.dbcp.domain.Group"
- alias="Group"/>
- <typeAliastype="com.xxt.ibatis.dbcp.domain.UserGroupLink"
- alias="UserGroupLink"/>
- </typeAliases>
- <environmentsdefault="development">
- <environmentid="development">
- <transactionManagertype="JDBC"/>
- <dataSourcetype="UNPOOLED">
- <propertyname="driver"value="${driver}"/>
- <propertyname="url"value="${url}"/>
- <propertyname="username"value="${username}"/>
- <propertyname="password"value="${password}"/>
- </dataSource>
- </environment>
- </environments>
- <mappers>
- <mapperresource="com/xxt/ibatis/dbcp/domain/user.map.xml"/>
- <mapperresource="com/xxt/ibatis/dbcp/domain/group.map.xml"/>
- </mappers>
- </configuration>
测试用例,代码如下:
- packagecom.xxt.ibatis.dbcp.test;
- importjava.io.Reader;
- importjava.text.SimpleDateFormat;
- importjava.util.List;
- importorg.junit.AfterClass;
- importorg.junit.BeforeClass;
- importorg.junit.Test;
- importorg.apache.ibatis.io.Resources;
- importorg.apache.ibatis.session.SqlSession;
- importorg.apache.ibatis.session.SqlSessionFactory;
- importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
- importcom.xxt.ibatis.dbcp.domain.Group;
- importcom.xxt.ibatis.dbcp.domain.User;
- importcom.xxt.ibatis.dbcp.domain.UserGroupLink;
- /**
- *@describe:测试用例
- *@author:Nirvana
- *@version:V1.02011-3-4下午03:21:17create
- */
- publicclassIbatisUserTest{
- privatefinalstaticStringIBATIS_CONFIG_XML="sqlMapConfig.xml";
- privatestaticSqlSessionsession;
- privateSimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-ddk:mm:ss");
- @BeforeClass
- publicstaticvoidsetUpBeforeClass()throwsException{
- Readerreader=Resources.getResourceAsReader(IBATIS_CONFIG_XML);//读取ibatis配置文件
- SqlSessionFactorysqlMapper=newSqlSessionFactoryBuilder().build(reader);
- session=sqlMapper.openSession(true);
- session.commit(false);//将默认提交事务属性设置为否
- }
- //保存用户信息
- @Test
- publicvoidsaveUserTest(){
- Useruser=newUser();
- user.setName("张三");
- user.setPassword("123456");
- session.insert("com.xxt.ibatis.dbcp.domain.User.saveUser",user);
- }
- //获取用户信息
- @Test
- publicvoidgetUserTest(){
- Useruser=(User)session.selectOne("com.xxt.ibatis.dbcp.domain.User.selectUser",1L);
- System.out.println("用户名:"+user.getName());
- System.out.println("用户密码:"+user.getPassword());
- System.out.println("用户创建日期:"+sdf.format(user.getCreateTime()));
- }
- //获取用户和用户所在组信息
- @Test
- publicvoidgetUserAndGroupTest(){
- Useruser=(User)session.selectOne("com.xxt.ibatis.dbcp.domain.User.selectUserGroup",4L);
- System.out.println(user.getName()+"所属组信息:");
- for(Groupgroup:user.getGroups()){
- System.out.println("组名:"+group.getName()+",组创建时间:"+sdf.format(group.getCreateTime()));
- }
- }
- //保存用户和用户所在组信息
- //当用户所在组不存在时,创建该组,并生成映射关系
- @Test
- publicvoidsaveUserAndGroupTest(){
- Useruser=newUser();
- user.setName("无常鬼");
- user.setPassword("wuchang");
- session.insert("com.xxt.ibatis.dbcp.domain.User.saveUser",user);
- GroupgroupImpl=(Group)session.selectOne("com.xxt.ibatis.dbcp.domain.Group.getGroupByName","用户组4");//获取组实例
- UserGroupLinkugl=newUserGroupLink();//声明User和Group实体间映射关系实例
- //查询到的组实例为空时的逻辑处理
- if(groupImpl==null){
- Groupgroup=newGroup();
- group.setName("用户组4");
- session.insert("com.xxt.ibatis.dbcp.domain.Group.saveGroup",group);//持久化创建好的组实例
- //设置映射关系实例相关的属性
- ugl.setUser(user);
- ugl.setGroup(group);
- session.insert("com.xxt.ibatis.dbcp.domain.User.saveRelativity",ugl);//持久化映射关系实力
- }else{
- ugl.setGroup(groupImpl);
- ugl.setUser(user);
- session.insert("com.xxt.ibatis.dbcp.domain.User.saveRelativity",ugl);
- }
- }
- //删除组信息的同时,取消组内所有的成员与该组的关联关系
- @Test
- publicvoiddeleteGroupTest(){
- Groupgroup=newGroup();
- //group.setId(1L);//以组id作为查询条件
- group.setName("用户组1");//以组name作为查询条件
- GroupgroupImpl=(Group)session.selectOne("com.xxt.ibatis.dbcp.domain.Group.selectGroupUser",group);//获取组实例
- //组实例存在时
- if(groupImpl!=null){
- List<User>users=groupImpl.getUsers();
- //查看用户组1中是否存在用户
- if(users!=null&&users.size()>0){
- //存在用户时,先删除组与用户的对应关系
- UserGroupLinkugl=newUserGroupLink();
- for(Useruser:users){
- ugl.setUser(user);
- ugl.setGroup(groupImpl);
- session.delete("com.xxt.ibatis.dbcp.domain.Group.deleteGroupUser",ugl);
- }
- }
- //删除组信息
- session.delete("com.xxt.ibatis.dbcp.domain.Group.deleteGroup",groupImpl);
- }else{
- thrownewRuntimeException("查询的组不存在!!");
- }
- }
- //更新组状态,当组状态由可见状态变成不可见时,取消该组下的用户与该组的映射关系
- @Test
- publicvoidupdateGroupStateTest(){
- Groupgroup=newGroup();
- group.setName("用户组2");
- GroupgroupImpl=(Group)session.selectOne("com.xxt.ibatis.dbcp.domain.Group.selectGroupUser",group);
- if(groupImpl!=null){
- intstate=groupImpl.getState()==1?0:1;
- //组状态由0变成1时,即由可见变为不可见
- if(state==1){
- List<User>users=groupImpl.getUsers();
- //查看用户组2中是否存在用户
- if(users!=null&&users.size()>0){
- //存在用户时,删除组与用户的对应关系
- UserGroupLinkugl=newUserGroupLink();
- for(Useruser:users){
- ugl.setUser(user);
- ugl.setGroup(groupImpl);
- session.delete("com.xxt.ibatis.dbcp.domain.Group.deleteGroupUser",ugl);
- }
- }
- }
- //更新组状态
- groupImpl.setState(state);
- }
- else{
- thrownewRuntimeException("查询的组不存在!!");
- }
- }
- @AfterClass
- publicstaticvoidtearDownAfterClass()throwsException{
- if(session!=null){
- session.commit();//提交事务
- session.close();//关闭连接
- }
- }
- }
评论
public class UserGroupLink {
private User user;
private Group group;
private Date createTime;
.....
}
文章中如上的映射,并没有将UserGroupLink的createDate映射到UserGroupLink,而是把groupCreateTime映射到Group的createTime属性
关联对象类UserGroupLink中的createTime属性该如何映射呢,在此例中并没有把UserGroupLink的createTime 映射出来,如果此关联对象类还有boolean enable等属性,可不可以直接将结果映射成UserGroupLink呢?,如何可以的话,该如何映射呢,谢谢。小弟最近在项目中要Mybatis,也遇到类似的case,不是很清楚如何解决,谢谢。