首先在之前建好的数据库mybatis
中新建6个表,关系如下(图中没有显示表与表具体的关系,比如一对多,多对多。只是画了箭头,表示有依赖关系)。表blog
代表博客,它由某位作者(表author
)所写,博客中有很多的文章(表post
),每篇文章有零或多条的评论(表comment
)和标签(表tag
),而表post_tag
里面存有文章和标签的id
(多对多的关系)。
具体的字段描述如下:
表中的数据如下:
表author
表blog
表tag
表post
表post_tag
表comment
在项目中新建实体类:
1.Author.java
package cn.edu.cqu.domains;
public class Author {
private int id;
private String username;
private String password;
private String email;
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
2.Blog.java
package cn.edu.cqu.domains;
import java.util.List;
public class Blog {
private Integer id;
private String title;
// 事实上,这个地方的authorId可以不需要了,因为有Author类了。
// private String authorId;
//为了连表查询
private Author author;
private List<Post> posts;
public Blog(Integer id) {
this.id = id;
}
public List<Post> getPosts() {
return posts;
}
public void setPosts(List<Post> posts) {
this.posts = posts;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
// public String getAuthorId() {
// return authorId;
// }
//
// public void setAuthorId(String authorId) {
// this.authorId = authorId;
// }
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
}
3.Tag.java
package cn.edu.cqu.domains;
public class Tag {
private Integer id;
private String name;
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;
}
}
4.PostTag.java
:
package cn.edu.cqu.domains;
public class PostTag {
private Integer id;
// 同上,不需要
// private Integer postId;
// private Integer tagId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
// public Integer getPostId() {
// return postId;
// }
//
// public void setPostId(Integer postId) {
// this.postId = postId;
// }
//
// public Integer getTagId() {
// return tagId;
// }
//
// public void setTagId(Integer tagId) {
// this.tagId = tagId;
// }
}
5.Post.java
package cn.edu.cqu.domains;
import java.util.List;
public class Post {
private Integer id;
// 因为类Blog里面有List<Post> posts了。
// private Integer blogId;
private String subject;
private String body;
//为了连表查询,一篇文章有很多评论,可以有很多标签,故用List存储。
private Author author;
private List<Comment> comments;
private List<Tag> tags;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
// public Integer getBlogId() {
// return blogId;
// }
//
// public void setBlogId(Integer blogId) {
// this.blogId = blogId;
// }
//
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
}
6.Comment.java
:
package cn.edu.cqu.domains;
public class Comment {
private Integer id;
// 同上的解释
// private Integer postId;
private String comment;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
// public Integer getPostId() {
// return postId;
// }
//
// public void setPostId(Integer postId) {
// this.postId = postId;
// }
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
在mybatis-config.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="config.properties">
</properties>
<!-- 全局配置参数,需要时再设置 -->
<!-- 一个配置完整的settings元素的示例如下 -->
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
<typeAliases>
<!-- 类型别名是为Java类型设置一个短的名字。它只和XML配置有关,
存在的意义仅在于用来减少类完全限定名的冗余 -->
<!-- 针对单个别名定义 type:类型的路径,类名不能写错,alias:别名 -->
<typeAlias type="cn.edu.cqu.domains.User" alias="user" />
<typeAlias type="cn.edu.cqu.domains.Location" alias="location" />
<!-- 这里就是我们定义的6个类,及其别名 -->
<typeAlias type="cn.edu.cqu.domains.Author" alias="author" />
<typeAlias type="cn.edu.cqu.domains.Blog" alias="blog" />
<typeAlias type="cn.edu.cqu.domains.Post" alias="post" />
<typeAlias type="cn.edu.cqu.domains.Comment" alias="comment" />
<typeAlias type="cn.edu.cqu.domains.Tag" alias="tag" />
<typeAlias type="cn.edu.cqu.domains.PostTag" alias="postTag" />
</typeAliases>
<!--尽管可以配置多个环境,每个 SqlSessionFactory 实例只能选择其一。
每个数据库对应一个 SqlSessionFactory 实例-->
<!-- 如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,
因为 Spring 模块会使用自带的管理器来覆盖前面的配置。 -->
<environments default="development">
<environment id="development">
<!-- JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
使用jdbc事务管理,事务控制由mybatis -->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理 -->
<!--有三种内建的数据源类型(也就是 type=”[UNPOOLED|POOLED|JNDI]”)-->
<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>
<!--通过resource方法一次加载一个映射文件 -->
<!--注意这里的路径和xml文件 -->
<mapper resource="mappers/user.xml" />
<mapper resource="mappers/location.xml" />
<!--由于实验中只关于blog的查询,故暂时只需要写一个 -->
<mapper resource="mappers/blog.xml" />
<!-- 批量加载mapper 指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载 -->
<!-- 遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 -->
<!-- 中 上边规范的前提是:使用的是mapper代理方法
<package name="mappers" />-->
</mappers>
</configuration>
最精彩的部分在blog.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="blog">
<resultMap id="detailedBlogResultMap" type="Blog">
<!-- 类Blog中必须要有包含一个参数的构造函数,参数为id,即主键名 -->
<constructor>
<idArg column="blog_id" javaType="int"/>
</constructor>
<result property="title" column="blog_title"/>
<!-- 一个博客只属于一个作者,故使用association -->
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<!-- 获取到用户的用户名,密码,email -->
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
</association>
<!-- 一个博客有很多文章,故使用collection -->
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<!-- 获取到文章的标题和内容 -->
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
<!-- 一篇文章只有一个作者,故使用association -->
<association property="author" javaType="Author"/>
<!-- 一篇文章有很多评论,故使用collection -->
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
<!-- 获取到评论的内容 -->
<result property="comment" column="comment_text"/>
</collection>
<!-- 一篇文章有很多标签,故使用collection -->
<collection property="tags" ofType="Tag" >
<id property="id" column="tag_id"/>
<!-- 获取到标签的内容 -->
<result property="name" column="tag_name"/>
</collection>
</collection>
</resultMap>
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
P.id as post_id,
P.blog_id as post_blog_id,
P.subject as post_subject,
P.body as post_body,
C.id as comment_id,
C.post_id as comment_post_id,
C.comment as comment_text,
T.id as tag_id,
T.name as tag_name
from blog B
left outer join author A on B.author_id = A.id
left outer join post P on B.id = P.blog_id
left outer join comment C on P.id = C.post_id
left outer join post_tag PT on PT.post_id = P.id
left outer join tag T on PT.tag_id = T.id
where B.id = #{id}
</select>
</mapper>
测试代码如下BlogTest.java
:
import cn.edu.cqu.domains.*;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class BlogTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
@Test
public void selectBlogDetailsTest() throws IOException {
// 通过工厂得到SqlSession
SqlSession sqlSession = this.getSqlSessionFactory().openSession();
//查询博客id为1的博客的所有信息
Blog blog = sqlSession.selectOne("blog.selectBlogDetails", 1);
System.out.println("Blog的id为:" + blog.getId());
System.out.println("Blog的标题为:" + blog.getTitle());
System.out.println("Blog的作者为:" + blog.getAuthor().getUsername());
System.out.println("博主的文章如下:");
for (Post p : blog.getPosts()) {
System.out.println("------------------------------------------------------------------------");
//System.out.println("文章id为:" + p.getId());
System.out.println("|主题:" + p.getSubject());
System.out.println("|内容:" + p.getBody());
System.out.print("|标签:" );
for (Tag tag : p.getTags()) {
System.out.print(tag.getName() + " ");
}
System.out.println();
System.out.println("|评论:");
for (Comment c : p.getComments()) {
System.out.println("|" + c.getComment());
}
System.out.println("------------------------------------------------------------------------");
}
sqlSession.close();
}
}
查询结果如下: