MyBatis教程3【映射文件和动态sql】
1.logj
在程序的运行的过程中为了便于查询sql的输出,需要引入logj添加依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
添加log4j.properties文件
log4j.rootCategory=DEBUG, stdout , R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=C:\\tools\\logs\\dpb.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
效果
2.传入参数【$和#】
由于MyBatis底层还是Jdbc,而Jdbc在操作数据库传递参数时,有两种方式,一种是使用Statement,还有一种是使用PreparedStatement: 使用statement时,存在SQL注入问题,PreparedStatement则通过预编译解决了SQL注入问题。
在MyBatis中,引入参数有两种方式,一种是使用#,还有一种是使用KaTeX parse error: Expected ‘EOF’, got ‘#‘ at position 7: ,其中,使用#̲对应了Jdbc种的Prepar…则对应了Jdbc种的Statement,因此在MyBatis种,推荐使用#。
#的使用
$的使用
加入可以使用KaTeX parse error: Expected ‘EOF’, got ‘#‘ at position 3: 替换#̲,注意,如果使用,需要在Mapper种指定参数名字
包装对象
javabean
public class UserWrapper {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
映射文件
<!-- 从包装对象中获取信息 包装对象的别名. 取信息 -->
<insert id="addUser4" parameterType="UserWrapper">
insert into t_user(name,age,favorites)values(#{user.name},#{user.age}
,#{user.favorites})
</insert>
测试
3.返回数据
ResultType
对于简单数据类型,例如查询总记录数、查询某一个用户名这一类返回值是一个基本数据类型的,直接写Java中的基本数据类型即可。
如果返回的是一个对象或者集合,并且对象中的属性和查询的字段名是一一对应的,那么resultType也可以直接写一个对象。
ResultMap
resultMap主要用来解决属性名和字段名不一致以及一对多、一对一查询等问题 字段名不一致时,首先可以通过取别名解决,例如Bean的定义如下:
User对象
private int id;
// 该类型和字段不一致
private String username;
private int age;
映射文件
解决方式一:给字段取别名,这里讲解解决方式二:
<resultMap type="com.sxt.bean.User" id="baseMap">
<id column="id" property="id"/>
<result property="username" column="name"/>
<result property="age" column="age"/>
</resultMap>
<select id="getUserById" resultMap="baseMap"
resultType="com.sxt.bean.User">
select id ,name ,age from t_user where id=${id}
</select>
主键回写
一般情况下,主键有两种生成方式:
主键自增长
自定义主键(一般可以使用UUID)
如果是第二种,主键一般是在Java代码中生成,然后传入数据库执行,如果是第一个主键自增长,此时,Java可能需要知道数据添加成功后的主键。 在MyBatis中,可以通过主键回填来解决这个问题(推荐)。
主键回填
<insert id="add" parameterType="user" useGeneratedKeys="true" keyProperty="id">
insert into t_user(username,password) values (#{name},#{password})
</insert>
selectKey
另外,可以利用MySQL自带的==last_insert_id()==函数查询刚刚插入的id
<insert id="add1" parameterType="user">
<selectKey keyProperty="id" resultType="int" >
select LAST_INSERT_ID()
</selectKey>
insert into t_user(username,password) values (#{name},#{password})
</insert>
动态sql语句
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
if语句
动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如
<select id="queryUser" resultMap="baseMap"
resultType="com.sxt.bean.User" parameterType="user">
select id ,name ,age from t_user
where 1 =1
<if test="username!=null">
and name = #{username}
</if>
</select>
// 接口
public List<User> queryUser(User user);
测试
where语句
在使用if语句做动态条件处理的时候如果所有条件都不满足,那么得到的SQL语句如下:
select * from t_user where
在这种情况下,我们一般会加一个1=1来匹配语法规则
<select id="queryUser" resultMap="baseMap"
resultType="com.sxt.bean.User" parameterType="user">
select id ,name ,age from t_user
where 1 =1
<if test="username!=null">
and name = #{username}
</if>
</select>
此时可以使用标签来处理这种情况
<select id="queryUser" resultMap="baseMap"
resultType="com.sxt.bean.User" parameterType="user">
select id ,name ,age from t_user
<where>
<if test="username!=null">
and name = #{username}
</if>
</where>
</select>
set语句
set主要也是用来解决更新问题的。
<update id="updateBookById">
update t_book
<set>
<if test="author!=null"> author=#{author},</if>
<if test="name!=null"> b_name=#{name},</if>
<if test="price!=null"> price=#{price},</if>
</set>
where id=#{id};
</update>
foreach语句
foreach用来遍历,遍历的对象可以是数组,也可以是集合
dao层接口
mapper映射文件
<select id="query1" resultType="User" resultMap="basemap">
select * from t_user
where id in
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</select>
<insert id="add2" parameterType="user" useGeneratedKeys="true" keyProperty="id">
insert into t_user(username,password) values
<foreach collection="users" separator="," item="user">
(#{user.name},#{user.password})
</foreach>
</insert>
bind元素
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。
<select id="getUserById" resultMap="baseMap" resultType="com.sxt.bean.User">
<!-- 声明了一个参数aaa 在后面就可以使用了 -->
<bind name="aaa" value="12"/>
select
id ,name ,age from t_user where id=${aaa}
</select>
sql块
sql片段一般用来定义sql中的列
关联关系
在关系型数据库中,表与表之间很少是独立与其他表没关系的。所以在实际开发过程中我们会碰到很多复杂的关联关系。在此我们来分析下载mybatis中怎么处理这些关系
1对1
我们有一张员工表(T_EMP),一张部门表(T_DEPT)。员工表中的一条记录对应于部门表中有且仅有一条记录。这就是一对一的关联关系。
查询每个员工的信息及对应的部门信息
部门对象
package com.sxt.bean;
public class Dept {
private Integer deptid;
private String deptname;
private String deptdesc;
public Integer getDeptid() {
return deptid;
}
public void setDeptid(Integer deptid) {
this.deptid = deptid;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
public String getDeptdesc() {
return deptdesc;
}
public void setDeptdesc(String deptdesc) {
this.deptdesc = deptdesc;
}
@Override
public String toString() {
return "Dept [deptid=" + deptid + ", deptname=" + deptname + ", deptdesc=" + deptdesc + "]";
}
}
员工对象
package com.sxt.bean;
public class Emp {
private Integer id;
private String name;
private Dept dept;
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;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp [id=" + id + ", name=" + name + ", dept=" + dept + "]";
}
}
映射文件处理
<?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="com.sxt.dao.EmpDao">
<resultMap type="Emp" id="basemap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<association property="dept" javaType="Dept">
<id property="deptid" column="deptid"/>
<result property="deptname" column="deptname"/>
<result property="deptdesc" column="deptdesc"/>
</association>
</resultMap>
<select id="query" resultMap="basemap">
SELECT t.*,t1.*
FROM t_emp t LEFT JOIN t_dept t1
on t.deptid=t1.deptid
</select>
</mapper>
1对多关系
查询出所有的部门信息及该部门下所有员工的信息
映射文件
<?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="com.sxt.dao.DeptDao">
<resultMap type="Dept" id="basemap">
<id property="deptid" column="deptid"/>
<result property="deptname" column="deptname"/>
<result property="deptdesc" column="deptdesc"/>
<collection property="emps" ofType="Emp">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="deptid" column="deptid"/>
</collection>
</resultMap>
<select id="query" resultMap="basemap">
SELECT t.*,t1.*
FROM t_dept t LEFT JOIN t_emp t1
on t.deptid=t1.deptid
</select>
</mapper>
还没有评论,来说两句吧...