1 select标签:执行查询操作。
当执行带有参数的SQL语句,如
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
传递的参数在SQL中会以?来标示,被传递到一个新的预处理的语句中。底层执行的是JDBC中的PreparedStatement,如下:
String selectPerson = "SELECT * FROM PERSON WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
select标签有很多属性,具体参考官方文档。
需要注意的点:1 当放回一个集合时,resultType设置的是集合中可以包含的类型。
2 insert, update 和 delete,处理增改删操作
insert, update 和 delete标签中的属性和Select标签中的属性类似。
需要注意的点:1 但数据库支持自动生成主键,那么设置 useGeneratedKeys=”true”,
然后再把 keyProperty 设置到目标属性上就OK了。如下:
<insert id="insert" parameterType="com.tang.text.pojo.Course" useGeneratedKeys="true" keyProperty="cno" >
insert into course (cname, cteachername)
values (#{cname,jdbcType=CHAR}, #{cteachername,jdbcType=CHAR})
</insert>
3 sql:定义可重复使用的SQL语句,可在其他位置引用。
定义一个可重复使用的SQL语句:
<sql id="Base_Column_List" >
cno, cname, cteachername
</sql>
在其他位置引用:
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from course
where cno = #{cno,jdbcType=INTEGER}
</select>
4 Parameters属性:为传递进SQl中的参数定义类型。
根据java中的面向对象的思想,万物皆为对象,当parameters属性设置为一个类时,执行传参时,将会对类中的属性和SQl中设置的字段#{}进行一一对应映射,如下中的Course中的各个字段个#{}中的字段。如果Course中的各个属性被查找到,将值传入预处理语句的参数中,同时可以在#{ }中设置jdbcType和javaType的类型。
<insert id="insert" parameterType="com.tang.text.pojo.Course" useGeneratedKeys="true" keyProperty="cno" >
insert into course (cname, cteachername)
values (#{cname,jdbcType=CHAR}, #{cteachername,jdbcType=CHAR})
</insert>
5 ResultMaps标签
各子标签说明:
摘自mybatis官方文档。
5.1 id和result:均是将列和对象中的属性进行映射,property为对象属性,column为列,javaType为java的类型,jdbcType为jdbc类型中的类型。id和result不同的是Id当比较对象实例时用到的标识属性。
5.2 constructor:构造方法注入:
<constructor>
<idArg column="id" javaType="int"/>
<arg column="username" javaType="String"/>
</constructor>
public class User {
//
...
public User(int id, String username) {
//
...
}
//
...
}
5.3 association:关联。加载关联两种类型如下:
嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。
嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。
5.3.1 关联嵌套查询
<select id="selectBlog" resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
</select>
<resultMap id="blogResult" type="Blog">
<association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap>
<select id="selectAuthor" resultType="Author">
SELECT * FROM AUTHOR WHERE ID = #{id}
</select>
说明:执行selectBlog中的SQL查询,执行完成后执行ResultMap关联的selectAuthor中的SQL,将返回结果集映射到author字段。
这种类型的关联加载会分散语句同时运行的消耗。但是对于大型集合将不会表现很好,会导致成千上万的SQL语句执行。
例:
表结构:
BlogMapper.xml:
<resultMap id="BaseResultMap" type="com.tang.text.pojo.Blog" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="userid" property="userid" jdbcType="INTEGER" />
<result column="blog" property="blog" jdbcType="VARCHAR" />
<association property="userUserid" column="userid" select="com.tang.text.dao.UserMapper.selectByPrimaryKey" />
</resultMap>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from blog
where id = #{id,jdbcType=INTEGER}
</select>
测试:
BlogMapper blogMapper=session.getMapper(BlogMapper.class);
Blog blog=blogMapper.selectByPrimaryKey(1);
System.out.println(blog.getUserUserid().getName());
5.3.2 关联嵌套结果
说明:通过将查询集中的各个字段对应的类通过ResultMap全部进行映射关联起来。如下:
查询:
<select id="selectBlog" resultMap="blogResult">
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
from Blog B left outer join Author A on B.author_id = A.id
where B.id = #{id}
</select>
对应映射集:
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" 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"/>
</association>
</resultMap>
当然也可在一个ResultMap中通过associate中的ResultMap字段将另外一个映射集引入。如下:
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/>
</resultMap>
<resultMap id="authorResult" type="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"/>
</resultMap>
6 集合:
SQL:
CREATE TABLE `blog` (
id int(11) NOT NULL AUTO_INCREMENT,
userid int(11) DEFAULT NULL,
blog varchar(50) DEFAULT NULL,
PRIMARY KEY (id),
KEY userid (userid),
FOREIGN KEY (userid) REFERENCES user (id)
)
INSERT INTO blog VALUES ('1', '1', '博客1');
INSERT INTO blog VALUES ('2', '1', '博客2');
INSERT INTO blog VALUES ('3', '1', '博客3');
CREATE TABLE user (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(255) DEFAULT NULL,
pwd varchar(255) DEFAULT NULL,
fatherid int(11) DEFAULT NULL,
PRIMARY KEY (id),
KEY fatherid (fatherid)
)
INSERT INTO `user` VALUES ('1', '张三', '123', null);
INSERT INTO `user` VALUES ('2', '李四', '456', null);
6.1 集合的嵌套查询:
UserMapper.xml
<resultMap id="BaseResultMap" type="com.tang.text.pojo.User" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="pwd" property="pwd" jdbcType="VARCHAR" />
<result column="fatherid" property="fatherid" jdbcType="INTEGER" />
<collection property="blogsUserid" ofType="com.tang.text.pojo.Blog" column="id" select="com.tang.text.dao.BlogMapper.selectByUserid" />
</resultMap>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from `user`
where id = #{id,jdbcType=INTEGER}
</select>
Cellection中的关联查询,Select中引用了一个在BlogMapper.xml中的SQL语句,相当于嵌套了一个子查询
BlogMapper.xml:
<resultMap id="BaseResultMap" type="com.tang.text.pojo.Blog" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="userid" property="userid" jdbcType="INTEGER" />
<result column="blog" property="blog" jdbcType="VARCHAR" />
<association property="userUserid" column="userid" select="com.tang.text.dao.UserMapper.selectByPrimaryKey" />
</resultMap>
select id="selectByUserid" resultMap="BaseResultMap" >
select <include refid="Base_Column_List" /> from blog where userid =#{userid}
</select>
测试:
UserMapper mapper = session.getMapper(UserMapper.class);
User user=mapper.selectByPrimaryKey(1);
for(Blog blog:user.getBlogsUserid()){
System.out.println(blog.getBlog());
}
结果:
6.2 集合的嵌套结果:
集合的嵌套结果适合哪种在Select后使用AS定点说明各个字段来与ResultMap中的column进行映射。关联嵌套结果无异。个人比较喜欢集合的嵌套查找。会查找出与之关联的信息,比较全,关键是使用ibator工具会直接生产代码,无需自己写。
7 鉴别器
与java中switch类似,将指定结果映射到指定的ResultMap中。
8 自动映射
说明:正如你在前面一节看到的,在简单的场景下,MyBatis可以替你自动映射查询结果。 如果遇到复杂的场景,你需要构建一个result
map。 但是在本节你将看到,你也可以混合使用这两种策略。 让我们到深一点的层面上看看自动映射是怎样工作的。
当自动映射查询结果时,MyBatis会获取sql返回的列名并在java类中查找相同名字的属性(忽略大小写)。 这意味着如果Mybatis发
现了ID列和id属性,Mybatis会将ID的值赋给id。
通常数据库列使用大写单词命名,单词间用下划线分隔;而java属性一般遵循驼峰命名法。 为了在这两种命名方式之间启用自动映
射,需要将 mapUnderscoreToCamelCase 设置为true。