Mapper映射语句高阶应用——ResultMap
resultMap 元素是MyBatis 中最重要最强大的元素。它就是让你远离 90%的需要从结果 集中取出数据的 JDBC代码的那个东西, 而且在一些情形下允许你做一些 JDBC 不支持的事 情。 事实上, 编写相似于对复杂语句联合映射这些等同的代码,也许可以跨过上千行的代码。 ResultMap 的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们 的关系。
我们通过一个连续的例子,来逐步讲解ReusltMap。
要进行ResultMap的实验,先设计数据库:
上述是数据库的E-R图。
- create database if not exists mybatis3;
- use mybatis3;
- drop table if exists tag;
- create table if not exists tag(
- id int primary key not null,
- name varchar(100) not null
- );
- drop table if exists author;
- create table if not exists author(
- id int primary key not null,
- username varchar(100) not null,
- password varchar(100) not null,
- email varchar(100),
- bio varchar(100),
- favourite_section varchar(100)
- );
- drop table if exists blog;
- create table if not exists blog(
- id int primary key not null,
- title varchar(100) not null,
- author_id int not null,
- constraint blog_author_fk foreign key(author_id) references author(id)
- on update cascade on delete cascade
- );
- drop table if exists post;
- create table if not exists post(
- id int primary key not null,
- blog_id int not null,
- author_id int not null,
- create_on date not null,
- section varchar(100),
- subject varchar(100),
- draft varchar(100),
- body varchar(200),
- constraint post_blog_fk foreign key(blog_id) references blog(id)
- on update cascade on delete cascade,
- constraint post_author_fk foreign key(author_id) references author(id)
- on update cascade on delete cascade
- );
- drop table if exists post_tag;
- create table if not exists post_tag(
- post_id int not null,
- tag_id int not null,
- primary key(post_id,tag_id),
- constraint postTag_post_fk foreign key(post_id) references post(id)
- on update cascade on delete cascade,
- constraint postTag_tag_fk foreign key(tag_id) references tag(id)
- on update cascade on delete cascade
- );
- drop table if exists comment;
- create table if not exists comment(
- id int primary key not null,
- post_id int not null,
- name varchar(100) not null,
- comment varchar(300),
- constraint comment_post_fk foreign key(post_id) references post(id)
- on update cascade on delete cascade
- );
- insert into tag values(111,'科技');
- insert into tag values(222,'文学');
- insert into tag values(333,'文档');
- insert into author values(1,'zjl','123','123@123.com','no','spring');
- insert into author values(2,'ddt','123','ddt@123.com','no','auto');
- insert into author values(3,'woya','123','woya@123.com','no','no');
- insert into author values(4,'yoiu','123','yoiu@123.com','no','what');
- insert into author values(5,'dwks','123','dwks@123.com','no','are');
- insert into blog values(1,'博客1',1);
- insert into blog values(2,'博客2',1);
- insert into blog values(3,'博客3',1);
- insert into blog values(4,'博客4',2);
- insert into blog values(5,'博客5',2);
- insert into blog values(6,'博客6',3);
- insert into blog values(7,'博客7',4);
- insert into blog values(8,'博客8',5);
- insert into post values(1,1,1,20130729,'section1','subject1','draft1','body1');
- insert into post values(2,1,1,20130729,'section2','subject2','draft2','body2');
- insert into post values(3,1,1,20130729,'section3','subject3','draft3','body3');
- insert into post values(4,2,1,20130729,'section4','subject4','draft4','body4');
- insert into post values(5,2,4,20130729,'section5','subject5','draft5','body5');
- insert into post values(6,2,2,20130729,'section6','subject6','draft6','body6');
- insert into post values(7,3,2,20130729,'section7','subject7','draft7','body7');
- insert into post values(8,3,4,20130729,'section8','subject8','draft8','body8');
- insert into post values(9,4,2,20130729,'section9','subject9','draft9','body9');
- insert into post values(10,5,5,20130729,'section10','subject10','draft10','body10');
- insert into post values(11,6,5,20130729,'section11','subject11','draft11','body11');
- insert into post values(12,7,5,20130729,'section12','subject12','draft12','body12');
- insert into post values(13,8,3,20130729,'section13','subject13','draft13','body13');
- insert into post_tag values(1,111);
- insert into post_tag values(1,333);
- insert into post_tag values(1,222);
- insert into post_tag values(2,111);
- insert into post_tag values(2,222);
- insert into post_tag values(2,333);
- insert into post_tag values(3,333);
- insert into post_tag values(4,333);
- insert into post_tag values(4,222);
- insert into post_tag values(4,111);
- insert into post_tag values(5,333);
- insert into post_tag values(6,333);
- insert into post_tag values(6,222);
- insert into post_tag values(7,333);
- insert into post_tag values(7,222);
- insert into post_tag values(7,111);
- insert into post_tag values(8,222);
- insert into post_tag values(9,222);
- insert into post_tag values(10,222);
- insert into post_tag values(11,222);
- insert into post_tag values(12,111);
- insert into post_tag values(13,111);
- insert into post_tag values(13,222);
- insert into post_tag values(13,333);
- insert into comment values(1,1,'评论1','评论内容1');
- insert into comment values(2,1,'评论2','评论内容2');
- insert into comment values(3,2,'评论3','评论内容3');
- insert into comment values(4,2,'评论4','评论内容4');
- insert into comment values(5,2,'评论5','评论内容5');
- insert into comment values(6,3,'评论6','评论内容6');
- insert into comment values(7,4,'评论7','评论内容7');
- insert into comment values(8,5,'评论8','评论内容8');
- insert into comment values(9,6,'评论9','评论内容9');
- insert into comment values(10,7,'评论10','评论内容10');
- insert into comment values(11,8,'评论11','评论内容11');
- insert into comment values(12,9,'评论12','评论内容12');
- insert into comment values(13,10,'评论13','评论内容13');
- insert into comment values(14,11,'评论14','评论内容14');
- insert into comment values(15,12,'评论15','评论内容15');
- insert into comment values(16,12,'评论16','评论内容16');
- insert into comment values(17,13,'评论17','评论内容17');
因为是进行MyBatis的ResultMap的相关实验,所以我也就不详细描述数据库设计的相关过程了,只是尽量做到数据库的复杂,包括一些一对一,一对多,多对一以及多对多联系。
所有的数据库涉及到了5个类,这些类为:Blog、Comment、Post、Tag、Author。不过这些类中的具体属形成员咱们暂时不添加,因为这关系到ResultMap的具体描述,这里我们不做具体解释,这些都会在之后的测试实验中提到。
前提工作已经做好了,现在可以开始测试:
基础ResultMap
我们先来看个简单的例子,这个例子只是包括了最简单的一些描述,没有复杂的联系(即外键)。
通过数据库,我们选择Tag这个类,因为它比较简单,就只有一个id和name的属性。
将Tag补充如下:
- package net.mybatis.model;
- public class Tag {
- private int id;
- private String name;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public String toString() {
- return this.getClass().getName() + ":[id:" + this.id + ",name:"
- + this.name + "]";
- }
- }
我们接下来要进行的是进行SQL语句的映射:
- <select id="test1" parameterType="int" resultType="Tag">
- select id,name from tag where id = #{id}
- </select>
以之前的挤出来说,我们很容易就可以写出上述的语句,不过这个跟ResultMap又有什么关系呢?
MyBatis其实已经在幕后自动创建了一个ResultMap与之对应,而我们不需要手动进行编写,它的规则是基于属性名来映射列到JavaBean的属性上。
当列名与JavaBean的属性名不一致的时候,可以使用as来设定一个别名,因为这个比较简单,我就直接套用MyBatis的文档来描述:
- <select id="selectUsers" parameterType="int" resultType="User">
- select
- user_id as "id",
- user_name as "userName",
- hashed_password as "hashedPassword"
- from
- some_table
- where
- id = #{id}
- </select>
很容易就知道as的具体用法了。
不过,我们也可以用ResultMap来定义,这个时候为了方便,我先用as来重新设定列名,再根据ResultMap更改回去:
- <select id="test1" parameterType="int" resultMap="test1Map">
- select
- id as tag_id,
- name
- from
- tag
- where
- id = #{id}
- </select>
- <resultMap type="Tag" id="test1Map">
- <id column="tag_id" property="id"/>
- <result column="name" property="name"/>
- </resultMap>
在这里我先将id的列名利用数据库的as别名为tag_id,之后,在映射的时候,通过ResultMap将,tag_id重新映射为id的属性名。
之前的select标签属性中的resultType则需要更改为resultMap,它的值为引用ResultMap标签的id值。
resultMap标签包含的子标签的具体属性,这里先简要介绍一下:
column:数据库返回过来的列名
property:要映射对象即(JavaBean)的属性名。
至于其他的具体属性将会在之后介绍。
高级结果映射
ResultMap中包含的子标签有如下几种:
标签名 |
描述 |
constructor |
构造方法 |
id |
一个ID结果 |
result |
普通属性字段 |
association |
一个复杂的类型关联,为一对多的形式 |
collection |
复杂类型的集合,为多对一的形式 |
discriminator |
根据结果值引用不同的ResultMap |
上述的子标签会在之后详细介绍,现在模糊不懂没有什么关系。
MyBatis建议我们的最佳实践也是让我们一步步进行了解,如果一下子进行过于复杂的结果映射,那么不出错是不可能的。
id&result
id标签为定义一个唯一标识,也就是数据库中诉说的主键
result则为一个普通的属性
id与result的标签的属性:
属性名 |
描述 |
property |
映射到javaBean的字段属性名 |
column |
数据库返回的列名 |
javaType |
该值(id或result)对应的java类型 |
jdbcType |
该值在数据库中的类型 |
typeHandler |
覆盖默认的类型处理器 |
构造方法
除了使用id和result来注入javaBean属性外,我们还可以通过构造方法的形式来注入属性,比如,我们将Tag类中的id和name都通过构造方法来构建:
- package net.mybatis.model;
- public class Tag {
- private Integer id;
- private String name;
- public Tag(Integer id,String name){
- this.id = id;
- this.name = name;
- }
- @Override
- public String toString() {
- return this.getClass().getName() + ":[id:" + this.id + ",name:"
- + this.name + "]";
- }
- }
- <resultMap type="Tag" id="test1Map">
- <constructor>
- <idArg column="tag_id" javaType="int"/>
- <arg column="name" javaType="string"/>
- </constructor>
- </resultMap>
其中,idArg为主键,arg为普通属性。
注意:在定义构造方法的时候要注意的是,必须以类的形式作为构造函数的参数。比如int,在构造的时候,必须更改为Integer,具体的原因是javaType声明的为int,这个在TypeAlianses中反射到的java类型为Integer,如果真的只想用int来使用构造,那么需要将javaType的int更改为_int,这个问题在文档中也没有提及,以至于在文档它的实际结果也是错误的。
关联
我们的数据库是一个博客数据库,因此,一片博文会对应一个作者,而一个作者拥有多篇博文,这在数据库中的关系为多对一。
而表示这种关系,我们可以使用association。
我们定义Author类:
- package net.mybatis.model;
- public class Author {
- private int id;
- private String username;
- private String password;
- private String email;
- private String bio;
- private String favouriteSection;
- 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;
- }
- public String getBio() {
- return bio;
- }
- public void setBio(String bio) {
- this.bio = bio;
- }
- public String getFavouriteSection() {
- return favouriteSection;
- }
- public void setFavouriteSection(String favouriteSection) {
- this.favouriteSection = favouriteSection;
- }
- @Override
- public String toString() {
- return this.getClass().getName() + ":[id:" + this.id + ",username:"
- + this.username + ",password:" + this.password + ",email:"
- + this.email + ",bio:" + this.bio + ",favouriteSection:"
- + this.favouriteSection + "]";
- }
- }
接着定义Blog类:
- package net.mybatis.model;
- public class Blog {
- private int id;
- private String title;
- private Author author;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public int getId() {
- return id;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public Author getAuthor() {
- return author;
- }
- public void setAuthor(Author author) {
- this.author = author;
- }
- @Override
- public String toString() {
- return this.getClass().getName() + ":[id:" + this.id + ",title:"
- + this.title + ",author:" + this.author + ",posts:" + "]";
- }
- }
我们在Blog类中加了一个Author的对象,这个是用来关联Author类的。
因为MyBatis在定义SQL映射后自动映射的过程中,需要JAVABean有一个联系的属性。
- <select id="test2" parameterType="int" resultMap="test2Map" >
- 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,
- A.bio as author_bio,
- A.favourite_section as author_favourite_section
- from
- Blog B
- left join Author A on (B.author_id = A.id)
- where
- B.id = #{id}
- </select>
- <resultMap type="Blog" id="test2Map">
- <id property="id" column="blog_id" javaType="int"/>
- <result property="title" column="blog_title" javaType="string"/>
- <association property="author" column="blog_author_id" javaType="Author">
- <id property="id" column="author_id" javaType="_int"/>
- <result property="username" column="author_username" javaType="string"/>
- <result property="password" column="author_password" javaType="string"/>
- <result property="email" column="author_email" javaType="string"/>
- <result property="bio" column="author_bio" javaType="string"/>
- <result property="favouriteSection" column="author_favourite_section" javaType="string"/>
- </association>
- </resultMap>
在<resultMap>标签中,存在着的association标签即为关联。
association的处理有两种方式,一种是select的嵌套查询,另一种是嵌套ResultMap结果。
嵌套ResultMap结果就是上述的例子,在这个例子中,还可以将<association>标签中的Author剥离开来,重新形成一个id为authorResult的resultMap,那么这个authorResult的resultMap就可以重用。而<assocation>只需要引用resultMap这个属性值为authorResult即可。
另外一种select的嵌套,如,可将上述的例子分解为:
- <resultMap type="Blog" id="test2Map">
- <id property="id" column="blog_id" javaType="int"/>
- <result property="title" column="blog_title" javaType="string"/>
- <association property="author" column="blog_author_id" javaType="Author" select="test2DivideSelect">
- </association>
- </resultMap>
- <select id="test2DivideSelect" parameterType="int" resultType="Author">
- select * from author where id = #{id}
- </select>
这种方式简单并且容易理解,不过它却有个致命的缺点,那就是如果查询的为大型数据集合和列表的情况下,那么所需要查询的SQL语句条数的数量会是惊人的。即是:“N+1”的情况,即需要对返回回来的N条数据进行细节添加。
如果Blog中存在一个相同的属性,这个属性,属性名字不同,但是类型相同,比如,Blog中存在一个author,如果还存在一个co-author又该如何,在这种情况
下,我们可以使用columnPrefix属性:
- <resultMap id="blogResult" type="Blog">
- <id property="id" column="blog_id" />
- <result property="title" column="blog_title" />
- <association property="author" resultMap="authorResult" />
- <association property="coAuthor" resultMap="authorResult"
- columnPrefix="co_" />
- </resultMap>
多对一映射
相对于上面的一对多映射,还有一种就是多对一映射,上述就说过,一篇博文对应有一个作者,那么一个作者必然对应有多篇博文。这个关系就是多对一的关系,而想要使用这个关系,那么就需要用到collection的标签。
将Author的类修改如下:
- package net.mybatis.model;
- import java.util.List;
- public class Author {
- private int id;
- private String username;
- private String password;
- private String email;
- private String bio;
- private String favouriteSection;
- private List<Blog> blogs;
- 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;
- }
- public String getBio() {
- return bio;
- }
- public void setBio(String bio) {
- this.bio = bio;
- }
- public String getFavouriteSection() {
- return favouriteSection;
- }
- public void setFavouriteSection(String favouriteSection) {
- this.favouriteSection = favouriteSection;
- }
- public List<Blog> getBlogs() {
- return blogs;
- }
- public void setBlogs(List<Blog> blogs) {
- this.blogs = blogs;
- }
- @Override
- public String toString() {
- return this.getClass().getName() + ":[id:" + this.id + ",username:"
- + this.username + ",password:" + this.password + ",email:"
- + this.email + ",bio:" + this.bio + ",favouriteSection:"
- + this.favouriteSection + ",blogs:"+this.blogs+"]";
- }
- }
我们添加了:
- private List<Blog> blogs;
这个属性,然后设置了它的setter和getter方法。
下面,如果我们要通过一个作者获取到他写了哪些博文,那么该如何做呢?
- <select id="test3" parameterType="int" resultMap="test3Map">
- select
- A.id as author_id,
- A.username as author_username,
- A.email as author_email,
- B.id as blog_id,
- B.title as blog_title,
- B.author_id as blog_author_id
- from
- Author A
- left join Blog B on (A.id = B.author_id)
- where
- A.id = #{id}
- </select>
- <resultMap type="Author" id="test3Map">
- <id column="author_id" property="id" javaType="_int"/>
- <result column="author_username" property="username" javaType="string"/>
- <result column="author_email" property="email" javaType="string"/>
- <collection column="blog_author_id" property="blogs" javaType="ArrayList" ofType="Blog">
- <id column="blog_id" property="id" javaType="_int"/>
- <result column="blog_title" property="title" javaType="string"/>
- </collection>
- </resultMap>
就如上述所说,collection即表示“多个”的关系,必须注意的是,一定要指定ofType属性,这个ofType属性指的是集合的元素类型,缺少这个属性,MyBatis会报出设定参数错误的提示。
就如同association一样,collection也分两种:一种为嵌套查询select,另一种为嵌套结果resultMap,用法也跟association一致,在这里就不再详细述说。
多对多
对于上述所说的一对多,多对一,数据库当然还有另外一种形式:多对多。这种关系在前面的基础上,应该已经能够猜的出来了,其实也就是在对多对的两个类中添加一个对方的私有List集合属性。这样在select映射中,不管用哪种为主体,都可以成功映射。
总包含
最后来个复杂的,包括了以上所有的描述:
- <select id="selectBlogDetails" parameterType="int"
- 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,
- A.bio as author_bio,
- A.favourite_section as author_favourite_section,
- P.id as post_id,
- P.blog_id as post_blog_id,
- P.author_id as post_author_id,
- P.create_on as post_create_on,
- P.section as post_section,
- P.subject as post_subject,
- P.draft as draft,
- P.body as post_body,
- C.id as comment_id,
- C.post_id as comment_post_id,
- C.name as comment_name,
- C.comment as comment_text,
- T.id as tag_id,
- T.name as tag_name
- from Blog B
- left join Author A on B.author_id = A.id
- left join Post P on B.id = P.blog_id
- left join Comment C on P.id = C.post_id
- left join Post_Tag PT on PT.post_id = P.id
- left join Tag T on PT.tag_id = T.id
- where B.id = #{id}
- </select>
- <resultMap id="detailedBlogResultMap" type="Blog">
- <constructor>
- <idArg column="blog_id" javaType="int" />
- </constructor>
- <result property="title" column="blog_title" />
- <association property="author" column="blog_author_id" javaType="Author">
- <id property="id" column="author_id" />
- <result property="username" column="author_username" />
- <result property="password" column="author_password" />
- <result property="email" column="author_email" />
- <result property="bio" column="author_bio" />
- <result property="favouriteSection" column="author_favourite_section" />
- </association>
- <!-- <association property="author" column="author_id" javaType="Author" select="selectAuthor"></association> -->
- <collection property="posts" javaType="ArrayList" column="post_blog_id" ofType="Post">
- <id property="id" column="post_id" />
- <result property="subject" column="post_subject" />
- <association property="author" column="post_author_id" javaType="Author" />
- <collection property="comments" javaType="ArrayList" column="comment_post_id" ofType="Comment">
- <id property="id" column="comment_id" />
- </collection>
- <collection property="tags" javaType="ArrayList" ofType="Tag">
- <id property="id" column="tag_id" />
- <result property="name" column="tag_name"/>
- </collection>
- </collection>
- </resultMap>
鉴别器
对于同一个数据库来说,我们往往通过不同的查询会返回不同的结果(即返回数据库的列不同)。在这种情况下,鉴别器的作用就凸显出来了。我们通过比较不同的鉴别器类型的值来判断使用哪个resultMap。
为了举这个例子,我们创建一个新的表:
- drop table if exists dis;
- create table if not exists dis(
- id int primary key not null,
- name varchar(100) not null,
- type_id int not null,
- test1 varchar(100),
- test2 varchar(100),
- test3 varchar(100)
- );
- insert into dis values(1,'dis1',1,'test11','test21','test31');
- insert into dis values(2,'dis2',1,'test12','test22','test32');
- insert into dis values(3,'dis3',2,'test13','test23','test33');
- insert into dis values(4,'dis4',2,'test14','test24','test34');
- insert into dis values(5,'dis5',2,'test15','test25','test35');
- insert into dis values(6,'dis6',3,'test16','test26','test36');
- insert into dis values(7,'dis7',3,'test17','test27','test37');
创建Dis类
- package net.mybatis.model;
- public class Dis {
- private int id;
- private String name;
- private int type_id;
- private String test1;
- private String test2;
- private String test3;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getType_id() {
- return type_id;
- }
- public void setType_id(int type_id) {
- this.type_id = type_id;
- }
- public String getTest1() {
- return test1;
- }
- public void setTest1(String test1) {
- this.test1 = test1;
- }
- public String getTest2() {
- return test2;
- }
- public void setTest2(String test2) {
- this.test2 = test2;
- }
- public String getTest3() {
- return test3;
- }
- public void setTest3(String test3) {
- this.test3 = test3;
- }
- }
接下来就是SQL的映射:
- <select id="test4" resultMap="test4Map">
- select
- id,
- name,
- type_id as type,
- test1,
- test2,
- test3
- from
- dis
- </select>
- <resultMap type="Dis" id="test4Map">
- <id column="id" property="id" javaType="_int"/>
- <result column="name" property="name" javaType="string"/>
- <discriminator javaType="_int" column="type" >
- <case value="1" resultType="string">
- <result column="test1" property="test1" javaType="string"/>
- </case>
- <case value="2" resultType="string">
- <result column="test2" property="test2" javaType="string"/>
- </case>
- <case value="3" resultType="string">
- <result column="test3" property="test3" javaType="string"/>
- </case>
- </discriminator>
- </resultMap>
在这里需要注意的是,选择的列必须要在类中写出来,而且每个case标签中的resultType属性必须设置,否则MyBatis会报空参数异常。
到现在为止,Mapper的高阶应用到此为止。
转载请注明出处,谢谢!
Mapper映射语句高阶应用——ResultMap的更多相关文章
- MySQL 数据库SQL语句——高阶版本2
MySQL 数据库SQL语句--高阶版本2 实验准备 数据库表配置: mysql -uroot -p show databases; create database train_ticket; use ...
- MySQL 数据库SQL语句——高阶版本1
MySQL 数据库SQL语句--高阶版本 实验准备,数据表配置 mysql -uroot -p show databases; create database train_ticket; use tr ...
- 我所理解的monad(4):函子(functor)是什么--可把范畴简单的看成高阶类型
大致介绍了幺半群(monoid)后,我们重新回顾最初引用wadler(haskell委员会成员,把monad引入haskell的家伙)的那句话: 现在我们来解读这句话中包含的另一个概念:自函子(End ...
- 深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap
上篇<深入浅出Mybatis系列(七)---mapper映射文件配置之insert.update.delete>介绍了insert.update.delete的用法,本篇将介绍select ...
- 深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap good
上篇<深入浅出Mybatis系列(七)---mapper映射文件配置之insert.update.delete>介绍了insert.update.delete的用法,本篇将介绍select ...
- 深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap[转]
上篇<深入浅出Mybatis系列(七)---mapper映射文件配置之insert.update.delete>介绍了insert.update.delete的用法,本篇将介绍select ...
- 深入浅出Mybatis系列八-mapper映射文件配置之select、resultMap
注:本文转载自南轲梦 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 上篇<深入浅出Mybatis系列(七)---mapper映射文件配置之inse ...
- MyBatis一对多映射简单查询案例(嵌套Mapper映射文件中的sql语句)
一.案例描述 书本类别表和书本信息表,查询书本类别表中的某一记录,连带查询出所有该类别书本的信息. 二.数据库表格 书本类别表(booktypeid,booktypename) 书本信息表(booki ...
- 深入理解javascript函数进阶系列第一篇——高阶函数
前面的话 前面的函数系列中介绍了函数的基础用法.从本文开始,将介绍javascript函数进阶系列,本文将详细介绍高阶函数 定义 高阶函数(higher-order function)指操作函数的函数 ...
随机推荐
- coconHashMap实现原理分析
1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1 ...
- POJ 3352 无向图边双连通分量,缩点,无重边
为什么写这道题还是因为昨天多校的第二题,是道图论,HDU 4612. 当时拿到题目的时候就知道是道模版题,但是苦于图论太弱.模版都太水,居然找不到. 虽然比赛的时候最后水过了,但是那个模版看的还是一知 ...
- android单选按钮选择,RadioGroup,radioButton
android单选按钮选择,RadioGroup,radioButton 14. 四 / android基础 / 没有评论 单选布局绑定 如何识别选择
- jade中mixin的使用
h2 mixin mixin lesson p jade study +lesson mixin study(name,courses) p #{name} ul.courses each cours ...
- Hadoop基本原理之一:MapReduce
1.为什么需要Hadoop 目前,一块硬盘容量约为1TB,读取速度约为100M/S,因此完成一块硬盘的读取需时约2.5小时(写入时间更长).若把数据放在同一硬盘上,且全部数据均需要同一个程序进行处理, ...
- debian系统下安装ssh服务
它是什么?? SSH 为 Secure Shell 的缩写,简单地说,SSH 为建立在应用层基础上的安全协议.SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议.利用 SSH 协议可 ...
- 《Programming WPF》翻译 第5章 7.控件模板
原文:<Programming WPF>翻译 第5章 7.控件模板 如果仔细的看我们当前的TTT游戏,会发现Button对象并没有完全为我们工作.哪些TTT面板有内圆角? 图5-14 这里 ...
- Linux 下的下载文件命令
普通文件只需 wget fileAddr 下载带有登录验证的文件 [chen@localhost Downloads]$ wget --user='av\bname' --ask-password ...
- 【转】notepad++设置字体和字体大小
原文网址:http://www.aichengxu.com/view/604 今天很多朋友问我怎么设置notepad++的代码字体和代码字体的大小,习惯了editplus的朋友可能会在notepad+ ...
- GitHub使用说明
登陆https://github.com/,并注册账号 从如下地址下载windows客户端:https://msysgit.googlecode.com/files/Git-1.8.4-preview ...