MyBatis 的 ResultMap 可以进行复杂的关联关系映射:
- 映射管理关系
- 集合映射
- 数据量太大时候,小心内存泄漏出问题
- 替换为分页查询
1.引子
在一个在线评论系统中,用户可以发帖,其他用户可以评论和转发,其实体关系如图:
创建SQL初始化脚本
create table blog_user(
u_id varchar(100),
u_name varchar(100),
u_password varchar(100),
PRIMARY KEY (u_id)
);
create table blog_post(
p_id varchar(100),
p_body varchar(1000),
p_user_id varchar(100),
PRIMARY KEY (p_id)
);
create table blog_comment(
c_id varchar(100),
c_body varchar(1000),
c_post_id varchar(100),
PRIMARY KEY (c_id)
);
create table blog_forward(
f_id varchar(100),
f_body varchar(1000),
f_post_id varchar(100),
PRIMARY KEY (f_id)
);
初始化数据:
insert into blog_user
(u_id, u_name, u_password)
values
('1', 'Tom', '123');
insert into blog_user
(u_id, u_name, u_password)
values
('2', 'Jerry', '123');
insert into blog_post
(p_id, p_body, p_user_id)
values
('1','今天天气不错!', '1');
insert into blog_post
(p_id, p_body, p_user_id)
values
('2','今天你吃了吗!', '1');
insert into blog_comment
(c_id, c_body, c_post_id)
values
(1,'雾霾太重', 1);
insert into blog_comment
(c_id, c_body, c_post_id)
values
(2,'是作为天气好', 1);
insert into blog_comment
(c_id, c_body, c_post_id)
values
(3,'做梦', 1);
以上数据表示:一个人发了一个帖子,有3个用户进行了回复。
2.创建映射实体
实体类:
public class User implements Serializable {
private static final long serialVersionUID = 2198506197294786297L;
private String id;
private String name;
private String password;
public User() {
}
public User(String id, String name, String password) {
super();
this.id = id;
this.name = name;
this.password = password;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", password=" + password + "]";
}
}
public class Comment implements Serializable{
private static final long serialVersionUID = 6832982316145348127L;
private String id;
private String body;
public Comment() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Comment other = (Comment) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "Comment [id=" + id + ", body=" + body + "]";
}
}
public class Post implements Serializable{
private static final long serialVersionUID = -4123583063151215606L;
private String id;
private String body;
//发帖人
private User user;
//帖子的回复
private List<Comment> comments =
new ArrayList<Comment>();
public Post() {
}
public Post(String id, String body, User user) {
super();
this.id = id;
this.body = body;
this.user = user;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Post other = (Post) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "Post [id=" + id + ", body=" + body + ", user=" + user + ", comments=" + comments + "]";
}
}
- 创建映射接口
public interface PostDao {
Post findPostById(String id);
}
- 为Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="cn.tedu.blog.dao.PostDao">
<!-- 自定义映射规则 -->
<resultMap id="postResultMap"
type="cn.tedu.blog.entity.Post">
<result property="id" column="p_id"/>
<result property="body" column="body"/>
<!-- association 关联,用于映射外键 -->
<association property="user"
column="p_user_id"
javaType="cn.tedu.blog.entity.User">
<id property="id" column="u_id"/>
<result property="name"
column="name"/>
<result property="password"
column="password"/>
</association>
<!-- 集合映射 -->
<collection property="comments"
javaType="java.util.ArrayList"
ofType="cn.tedu.blog.entity.Comment"
column="p_id"
select="selectComment">
</collection>
</resultMap>
<select id="selectComment"
resultType="cn.tedu.blog.entity.Comment">
select
c_id as id,
c_body as body
from
blog_comment
where
c_post_id=#{p_id}
</select>
<select id="findPostById"
parameterType="string"
resultMap="postResultMap">
select
p.p_id ,
p.p_body as body,
p.p_user_id,
u.u_id,
u.u_name as name,
u.u_password as password
from
blog_post p
left outer join blog_user u
on p.p_user_id=u.u_id
where
p_id=#{id}
</select>
</mapper>
**其中:
利用resultMap处理复杂映射
collection用于映射集合
assocition用于关联映射**
4.配置Spring
配置spring-mybatis.xml文件:
<bean id="mapperScanner2"
class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描cn.tedu.note.dao中的mapper接口 -->
<property name="basePackage"
value="cn.tedu.blog.dao" />
</bean>
5.测试
@Test
public void testFindPostById(){
PostDao dao = ctx.getBean(
"postDao",PostDao.class);
Post post = dao.findPostById("1");
System.out.println(post);
}