mybatis的了解
2018-01-17 19:40
344 查看
一、mybatis的框架结构
过程说明:
1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped
Statement对象,sql的id即是Mapped
statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
注意事项:
1.代码说明
public class User_select {
public static void main(String[] args) throws IOException {
//加载配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//根据mytais的配置创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//根据SqlSessionFactory创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过sqlSession查询用户信息(发起数据库操作)
//第一个参数statement:指定mapper映射文件中statement的id,指定 时需要前边加上statement所属的命名空间
//第二个参数parameter,指定 输入参数
//selectOne返回的是单条记录,如果select返回多条记录(list集合),使用selectOne会报错
//根据映射文件中的resultType指定输出类型
User user = sqlSession.selectOne("test.findUserById", 10);
//遍历查询结果
System.out.println(user);
//查询用户列表
//selectList表示查询一个结果集(可以是一条或多条)
List<User> list = sqlSession.selectList("test.findUserList", "张");
System.out.println(list.size());
//关闭sqlSession
sqlSession.close();
}
}
2、sqlSession的使用注意事项
SqlSessionFactory:会话工厂,用于创建SqlSession,SqlSessionFactory一旦创建成功,不用每次创建工厂,建议单例模式使用工厂。如果和spring整合后,由spring来管理SqlSessionFactory,在spring容器中SqlSessionFactory是一个单例对象。
SqlSession:(重点)是一个面向用户的接口,通过SqlSessionFactory获取SqlSession,每次数据操作都需要创建新的SqlSession,SqlSession
不是线程安全,最佳应用场合是方法体内,在方法中定义一个SqlSession局部变量。
二、mybatis作为持久层框架在开发过程中常用的两种配置方式
1、原始dao层的使用方式
这种情况:需要开发dao接口和dao的实现类。
public interface UserDao {
//根据用户id查询用户信息
public User findUserById(int id) throws Exception;
//添加用户
public void insertUser(User user) throws Exception;
//查询用户列表
public List<User> findUserList()throws Exception;
}
具体代码参考:https://github.com/libolibolibo/mybatis1217_1.git
2、使用mybatis的动态代理的方法
2.1、使用mybatis动态代理的好处
在开发过程中,只需要开发dao接口、接口对应的mapper.xml文件就可以了;
2.2、使用mybatis动态代理开发的原理
通过mybatis动态代理规则的配置,根据映射文件会生成dao接口实现类的代理对象,这个就相当于mybatis自己通过映射文件的配置,自己生成类dao接口的实现类,进而动态的调用statement语句;
2.3、使用mybatis的动态代理的规则配置
2.31、 在mapper.xml中将namespace设置为mapper.java接口的全限定名
2.32、 将mapper.java接口的方法名和mapper.xml中statement的id保持一致。
2.33、 将mapper.java接口的方法输入参数类型和mapper.xml中statement的parameterType保持一致
2.34、 将mapper.java接口的方法输出 结果类型和mapper.xml中statement的resultType保持一致
2.4注意:mybatis在调用查询的时候是调用selectOne还是selectList取决于dao接口的返回值,但是resultType保持不变;
Mybatis生成代理对象时,根据statement的标签决定调用
SqlSession的方法(select、insert、update..)
根据上边接口方法返回值
类型来决定 是调用 selectOne还是selectList,如果返回的是单个对象,动态代理调用selectOne(),如果返回的是集合对象,动态代理调用selectList()。
<select id="findUserById" parameterType="int" resultType="user">
SELECT * FROM USER WHERE id = #{id}
</select>
具体的代码示例:https://github.com/libolibolibo/mybatis1217_2.git
三、mybatis框架的全局的配置文件(一般名称为SqlMapConfig.xml)说明,这个在开发过程中使用比较少,一般在与spring整合后就不使用该文件了,但是要了解
1、全局配置文件的作用
SqlMapConfig.xml作为mybatis的全局配置文件,配置内容包括:数据库环境、mapper定义、全局参数设置......
properties(属性)
properties属性文件一般使用在,将数据库连接参数单独在一个properties文件中配置,好处是:方便系统升级维护。
settings(全局配置参数)
mybaits框架运行设置一些全局配置参数,比如:开启二级缓存 ,开启延迟载。。。
在ibatis中有一些设置性能参数(最大线程数、最大请求数。。),在mybatis中没有这些性能参数。
注意:设置全局参数会影响mybatis框架运行,谨慎设置。
typeAliases(类型别名)
在parameterType和resultType设置时,为了方便编码,定义别名代替pojo的全路径。
typeHandlers(类型处理器)
类型处理器用于java类型和jdbc类型映射:
Mybatis提供 的类型处理器满足日常需要。
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
四、mybatis的映射文件配置说明(一般命名为xxxMapper.xml)
(一)、主键返回问题
需求 :对于新增的记录,需要将主键返回到pojo中,就可以从pojo中获取新添加的记录id。
自增主键生成 Uuid主键生成时机区别:
自增主键在insert语句执行后生成 的。
Uuid主键在insert语句执行前生成 的。
1、Mysql自增主键获取
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<!--
keyProperty:将主键设置到pojo中哪个属性中
order:selectKey中sql执行的时机
resultType:selectKey中sql执行的结果类型
LAST_INSERT_ID:是insert后获取自增主键值
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address,detail,score)
values(#{username},#{birthday},#{sex},#{address},#{detail},#{score})
</insert>
2、 Uuid主键获取
Uuid主键在insert语句执行前生成 的
如果使用uuid获取主键,定义selectkey
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<!--
keyProperty:将主键设置到pojo中哪个属性中
order:selectKey中sql执行的时机
resultType:selectKey中sql执行的结果类型
LAST_INSERT_ID:是insert后获取自增主键值
-->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address,detail,score)
values(#{id},#{username},#{birthday},#{sex},#{address},#{detail},#{score})
</insert>
如果不用selectKey,也可以在调用SqlSession.insert()前,在输入参数设置id值
(生成uuid,设置到user的id属性中。)。
3、Oracle主键返回
Oracle没有自增主键,使用oracle的序列(可以生成流水号,类似 自增主键)生成主键。
通过序列获取流水号方法:
Select 序列名.next.val from dual
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<!--
keyProperty:将主键设置到pojo中哪个属性中
order:selectKey中sql执行的时机
resultType:selectKey中sql执行的结果类型
LAST_INSERT_ID:是insert后获取自增主键值
-->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
Select 序列名.next.val from dual
</selectKey>
insert into user(id,username,birthday,sex,address,detail,score)
values(#{id},#{username},#{birthday},#{sex},#{address},#{detail},#{score})
</insert>
(二)、parameterType(输入类型)
parameterType:用于设置输入参数的类型。
#{}:表示占位符,如果获取简单类型,#{}中可以使用value或其它名称 。有效防止sql注入。使用#{}设置参数无需考虑参数的类型。
如果使用#{}比较日期字段,select * from tablename where birthday >=#{birthday}
${}:表示sql拼接,如果获取简单类型,${}中只能使用value
。无法防止sql注入。使用${}设置参数必须考虑参数的类型,比如:使用oracle查询条件是日期类型,如果使用${},必须人为将${}两边加单引号通过to_date转日期。(只是表示简单的字符串拼接,而没有mybatis的映射关系)
Select * from table where birthday >=to_date(‘${birthday}’,’yyyy-MM-dd’)
在没有特殊要求的情况下,建议使用#{}占位符
有些情况必须使用${},
比如:需要动态拼接表名,Select * from ${tablename}
动态拼接排序字段:select * from tablename order by ${username} desc
输入参数为pojo自定义对象时,在sql中使用${}和#{}获取pojo的属性。
定义包装对象将查询条件(pojo)以类组合的方式包装起来。
parameterType使用包装对象:
包装类
映射文件.xml
<!-- 查询用户列表 根据用户名称和用户性别查询用户列表 -->
<select id="findUserList" parameterType="queryVo" resultType="user">
select id,username username_ from user
<!-- where自动将第一个and去掉 -->
<where>
<!-- 这里调用 queryVo的getUser方法获 取user的值 -->
<if test="user!=null">
<!-- 这里调用 queryVo的user的getUsername方法获取username的值 -->
<if test="user.username!=null and user.username!=''">
and user.username = #{user.username}
</if>
<if test="user.sex!=null and user.sex!=''">
and user.sex = #{user.sex}
</if>
</if>
<if test="ids!=null">
<foreach collection="ids" item="id" open="AND ("
separator="OR" close=")">
id =#{id}
</foreach>
<!-- AND id IN (10,89,16) -->
<!-- <foreach collection="ids" item="id" open="AND id IN ("
separator="," close=")">
#{id}
</foreach> -->
</if>
</where>
</select>
Sql映射文件定义如下:
<!-- 传递hashmap综合查询用户信息 -->
<select id="selectUserByHashmap" parameterType="hashmap" resultType="user">
select * from user where id=#{id} and username like '%${username}%'
</select>
如果全部字段和pojo的属性名不一致,映射生成 的java对象为空,只要有一个字段和pojo属性名一致,映射生成
的java对象不为空。
结论:sql查询字段名和pojo的属性名一致才能映射成功。
不管select返回的是单个 对象还是集合对象,resultType要指定单条记录映射的java对象。
l Mapper.xml
<select id="findUserListReturnMap" parameterType="queryVo" resultType="hashmap">
select id,username username_ from user where username = #{user.username} and sex=#{user.sex}
</select>
l Mapper.java
Public Map findUserListReturnMap(QueryVo queryVo);
建议不使用map作为返回值 ,因为需要对key在代码中硬编码。
(四)、mybatis的动态sql
Mybatis提供 了很多标签,用于拼接sql语句。
if标签
where标签
set标签
foreach标签
<?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="cn.itcast.mybatis.mapper.UserMapperCustom">
<!-- sql片段 -->
<!--
用户查询条件
id:在namespace唯 一标识
建议以单表抽取查询条件
-->
<sql id="query_user_where">
<!-- 这里调用 queryVo的getUser方法获 取user的值 -->
<if test="user!=null">
<!-- 这里调用 queryVo的user的getUsername方法获取username的值 -->
<if test="user.username!=null and user.username!=''">
and user.username = #{user.username}
</if>
<if test="user.sex!=null and user.sex!=''">
and user.sex = #{user.sex}
</if>
</if>
<if test="ids!=null">
<!-- 根据传入id数组构造查询条件 -->
<!-- AND (id =10 OR id =89 OR id=16) -->
<!-- 遍历ids数组
collection:集合,ids数组
item:遍历的每个对象
open:开始遍历时拼接的sql
separator:遍历的间隔符号
close:结束 遍历时拼接的sql
-->
<foreach collection="ids" item="id" open="AND ("
separator="OR" close=")">
id =#{id}
</foreach>
<!-- AND id IN (10,89,16) -->
<!-- <foreach collection="ids" item="id" open="AND id IN ("
separator="," close=")">
#{id}
</foreach> -->
</if>
</sql>
<!-- 定义resultMap,将用户查询的字段和user这个pojo的属性名作一个对应关系 -->
<!--
type:最终映射的java对象。
id:resultMap的唯一标识
-->
<resultMap type="user" id="userListResultMap">
<!-- id标签:查询结果集的唯 一标识 列(主键或唯 一标识 )
column:sql查询字段名(列名)
property:pojo的属性名
result标签:普通列
-->
<id column="id_" property="id"/>
<result column="username_" property="username"/>
<result column="birthday_" property="birthday"/>
</resultMap>
<!-- 查询用户列表 根据用户名称和用户性别查询用户列表 -->
<select id="findUserList" parameterType="queryVo" resultType="user">
select id,username username_ from user
<!-- where自动将第一个and去掉 -->
<where>
<!--
refid:指定 sql片段的id,如果要引用其它命名空间的sql片段,需要前边加namespace
-->
<include refid="query_user_where"/>
</where>
</select>
<!-- 查询用户列表 根据用户名称和用户性别查询用户列表 -->
<select id="findUserListResultMap" parameterType="queryVo" resultMap="userListResultMap">
select id id_,username username_,birthday birthday_ from user
<!-- where自动将第一个and去掉 -->
<where>
<!--
refid:指定 sql片段的id,如果要引用其它命名空间的sql片段,需要前边加namespace
-->
<include refid="query_user_where"/>
</where>
</select>
<!-- 查询用户列表总数 用于分页查询 -->
<select id="findUserCount" parameterType="queryVo" resultType="int">
select count(*) from user
<!-- where自动将第一个and去掉 -->
<where>
<!--
refid:指定 sql片段的id,如果要引用其它命名空间的sql片段,需要前边加namespace
-->
<include refid="query_user_where"/>
</where>
</select>
</mapper>
具体代码示例,看上面两个项目的代码吧!
过程说明:
1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped
Statement对象,sql的id即是Mapped
statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped
Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
注意事项:
1.代码说明
public class User_select {
public static void main(String[] args) throws IOException {
//加载配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//根据mytais的配置创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//根据SqlSessionFactory创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过sqlSession查询用户信息(发起数据库操作)
//第一个参数statement:指定mapper映射文件中statement的id,指定 时需要前边加上statement所属的命名空间
//第二个参数parameter,指定 输入参数
//selectOne返回的是单条记录,如果select返回多条记录(list集合),使用selectOne会报错
//根据映射文件中的resultType指定输出类型
User user = sqlSession.selectOne("test.findUserById", 10);
//遍历查询结果
System.out.println(user);
//查询用户列表
//selectList表示查询一个结果集(可以是一条或多条)
List<User> list = sqlSession.selectList("test.findUserList", "张");
System.out.println(list.size());
//关闭sqlSession
sqlSession.close();
}
}
2、sqlSession的使用注意事项
SqlSession使用方法
SqlSessionFactoryBuilder:用于创建SqlSessionFactory,将SqlSessionFactoryBuilder当成工具类使用。SqlSessionFactory:会话工厂,用于创建SqlSession,SqlSessionFactory一旦创建成功,不用每次创建工厂,建议单例模式使用工厂。如果和spring整合后,由spring来管理SqlSessionFactory,在spring容器中SqlSessionFactory是一个单例对象。
SqlSession:(重点)是一个面向用户的接口,通过SqlSessionFactory获取SqlSession,每次数据操作都需要创建新的SqlSession,SqlSession
不是线程安全,最佳应用场合是方法体内,在方法中定义一个SqlSession局部变量。
二、mybatis作为持久层框架在开发过程中常用的两种配置方式
1、原始dao层的使用方式
这种情况:需要开发dao接口和dao的实现类。
public interface UserDao {
//根据用户id查询用户信息
public User findUserById(int id) throws Exception;
//添加用户
public void insertUser(User user) throws Exception;
//查询用户列表
public List<User> findUserList()throws Exception;
}
public class UserDaoImpl implements UserDao { // 注入SqlSessionFactory private SqlSessionFactory sqlSessionFactory; public UserDa 14f0e oImpl(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } @Override public User findUserById(int id) throws Exception { // 根据SqlSessionFactory创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession查询用户信息(发起数据库操作) // 第一个参数statement:指定mapper映射文件中statement的id,指定 时需要前边加上statement所属的命名空间 // 第二个参数parameter,指定 输入参数 // selectOne返回的是单条记录,如果select返回多条记录(list集合),使用selectOne会报错 // 根据映射文件中的resultType指定输出类型 User user = sqlSession.selectOne("test.findUserById", id); // 遍历查询结果 // System.out.println(user); return user; } @Override public void insertUser(User user) throws Exception { // 根据SqlSessionFactory创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.insert("test.insertUser", user); sqlSession.commit(); sqlSession.close(); } @Override public List<User> findUserList() throws Exception { // 根据SqlSessionFactory创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession查询用户信息(发起数据库操作) // 第一个参数statement:指定mapper映射文件中statement的id,指定 时需要前边加上statement所属的命名空间 // 第二个参数parameter,指定 输入参数 // selectOne返回的是单条记录,如果select返回多条记录(list集合),使用selectOne会报错 // 根据映射文件中的resultType指定输出类型 // 查询用户列表 // selectList表示查询一个结果集(可以是一条或多条) List<User> list = sqlSession.selectList("test.findUserList", "张"); System.out.println(list.size()); return list; } }
具体代码参考:https://github.com/libolibolibo/mybatis1217_1.git
2、使用mybatis的动态代理的方法
2.1、使用mybatis动态代理的好处
在开发过程中,只需要开发dao接口、接口对应的mapper.xml文件就可以了;
2.2、使用mybatis动态代理开发的原理
通过mybatis动态代理规则的配置,根据映射文件会生成dao接口实现类的代理对象,这个就相当于mybatis自己通过映射文件的配置,自己生成类dao接口的实现类,进而动态的调用statement语句;
2.3、使用mybatis的动态代理的规则配置
2.31、 在mapper.xml中将namespace设置为mapper.java接口的全限定名
2.32、 将mapper.java接口的方法名和mapper.xml中statement的id保持一致。
2.33、 将mapper.java接口的方法输入参数类型和mapper.xml中statement的parameterType保持一致
2.34、 将mapper.java接口的方法输出 结果类型和mapper.xml中statement的resultType保持一致
2.4注意:mybatis在调用查询的时候是调用selectOne还是selectList取决于dao接口的返回值,但是resultType保持不变;
Mybatis生成代理对象时,根据statement的标签决定调用
SqlSession的方法(select、insert、update..)
根据上边接口方法返回值
类型来决定 是调用 selectOne还是selectList,如果返回的是单个对象,动态代理调用selectOne(),如果返回的是集合对象,动态代理调用selectList()。
<select id="findUserById" parameterType="int" resultType="user">
SELECT * FROM USER WHERE id = #{id}
</select>
<select id="findUserList" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User" > SELECT * FROM USER WHERE username LIKE '%${value}%' </select>
public interface UserMapper { //根据用户id查询用户信息 public User findUserById(int id) throws Exception; //查询用户列表 public List<User> findUserList(String username)throws Exception; }
具体的代码示例:https://github.com/libolibolibo/mybatis1217_2.git
三、mybatis框架的全局的配置文件(一般名称为SqlMapConfig.xml)说明,这个在开发过程中使用比较少,一般在与spring整合后就不使用该文件了,但是要了解
1、全局配置文件的作用
SqlMapConfig.xml作为mybatis的全局配置文件,配置内容包括:数据库环境、mapper定义、全局参数设置......
properties(属性)
properties属性文件一般使用在,将数据库连接参数单独在一个properties文件中配置,好处是:方便系统升级维护。
settings(全局配置参数)
mybaits框架运行设置一些全局配置参数,比如:开启二级缓存 ,开启延迟载。。。
在ibatis中有一些设置性能参数(最大线程数、最大请求数。。),在mybatis中没有这些性能参数。
注意:设置全局参数会影响mybatis框架运行,谨慎设置。
typeAliases(类型别名)
在parameterType和resultType设置时,为了方便编码,定义别名代替pojo的全路径。
typeHandlers(类型处理器)
类型处理器用于java类型和jdbc类型映射:
Mybatis提供 的类型处理器满足日常需要。
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
<?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="db.properties" /> <!-- 全局配置参数 --> <!-- settings></settings> --> <!-- 定义别名 --> <typeAliases> <!-- 单个别名定义 type:pojo的路径 alias:别名的名称 --> <!-- <typeAlias type="cn.itcast.mybatis.po.User" alias="user"/> --> <!-- 批量别名定义 name:指定包名,将包下边的所有pojo定义别名 ,别名为类名(首字母大写或小写都行) --> <package name="cn.itcast.mybatis.po"/> </typeAliases> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <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> <!-- 配置mapper映射文件 --> <mappers> <!-- resource方式 在UserMapper.xml,定义namespace为mapper接口的地址,映射文件通过namespace找到对应的mapper接口文件 --> <!-- <mapper resource="sqlmap/UserMapper.xml" /> --> <!-- class方式 class:指定 mapper接口的地址 遵循规则:将mapper.xml和mapper.java文件放在一个目录 且文件名相同 --> <!-- <mapper class="cn.itcast.mybatis.mapper.UserMapper"/> --> <!--批量mapper扫描 遵循规则:将mapper.xml和mapper.java文件放在一个目录 且文件名相同 --> <package name="cn.itcast.mybatis.mapper"/> </mappers> </configuration>
四、mybatis的映射文件配置说明(一般命名为xxxMapper.xml)
(一)、主键返回问题
需求 :对于新增的记录,需要将主键返回到pojo中,就可以从pojo中获取新添加的记录id。
自增主键生成 Uuid主键生成时机区别:
自增主键在insert语句执行后生成 的。
Uuid主键在insert语句执行前生成 的。
1、Mysql自增主键获取
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<!--
keyProperty:将主键设置到pojo中哪个属性中
order:selectKey中sql执行的时机
resultType:selectKey中sql执行的结果类型
LAST_INSERT_ID:是insert后获取自增主键值
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address,detail,score)
values(#{username},#{birthday},#{sex},#{address},#{detail},#{score})
</insert>
2、 Uuid主键获取
Uuid主键在insert语句执行前生成 的
如果使用uuid获取主键,定义selectkey
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<!--
keyProperty:将主键设置到pojo中哪个属性中
order:selectKey中sql执行的时机
resultType:selectKey中sql执行的结果类型
LAST_INSERT_ID:是insert后获取自增主键值
-->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address,detail,score)
values(#{id},#{username},#{birthday},#{sex},#{address},#{detail},#{score})
</insert>
如果不用selectKey,也可以在调用SqlSession.insert()前,在输入参数设置id值
(生成uuid,设置到user的id属性中。)。
3、Oracle主键返回
Oracle没有自增主键,使用oracle的序列(可以生成流水号,类似 自增主键)生成主键。
通过序列获取流水号方法:
Select 序列名.next.val from dual
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<!--
keyProperty:将主键设置到pojo中哪个属性中
order:selectKey中sql执行的时机
resultType:selectKey中sql执行的结果类型
LAST_INSERT_ID:是insert后获取自增主键值
-->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
Select 序列名.next.val from dual
</selectKey>
insert into user(id,username,birthday,sex,address,detail,score)
values(#{id},#{username},#{birthday},#{sex},#{address},#{detail},#{score})
</insert>
(二)、parameterType(输入类型)
parameterType:用于设置输入参数的类型。
1、#{}与${}
#{}:表示占位符,如果获取简单类型,#{}中可以使用value或其它名称 。有效防止sql注入。使用#{}设置参数无需考虑参数的类型。
如果使用#{}比较日期字段,select * from tablename where birthday >=#{birthday}
${}:表示sql拼接,如果获取简单类型,${}中只能使用value
。无法防止sql注入。使用${}设置参数必须考虑参数的类型,比如:使用oracle查询条件是日期类型,如果使用${},必须人为将${}两边加单引号通过to_date转日期。(只是表示简单的字符串拼接,而没有mybatis的映射关系)
Select * from table where birthday >=to_date(‘${birthday}’,’yyyy-MM-dd’)
在没有特殊要求的情况下,建议使用#{}占位符
有些情况必须使用${},
比如:需要动态拼接表名,Select * from ${tablename}
动态拼接排序字段:select * from tablename order by ${username} desc
2、 传递pojo对象
2.1、parameterType指定输入参数为pojo自定义对象时,在sql中使用${}和#{}获取pojo的属性。
2.2、 包装对象使用
开发中使用pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(是另一个pojo),使用包装对象传递输入参数。定义包装对象将查询条件(pojo)以类组合的方式包装起来。
parameterType使用包装对象:
包装类
public class QueryVo { //用户查询条件 //为了查询条件扩展方便,基于po的基础上自定义的pojo,继承于Po private UserCustom userCustom; private User user; private int[] ids; public UserCustom getUserCustom() { return userCustom; } public void setUserCustom(UserCustom userCustom) { this.userCustom = userCustom; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public int[] getIds() { return ids; } public void setIds(int[] ids) { this.ids = ids; } //基它的查询条件 }
public class UserCustom extends User { //学生类型,扩展字段 private String groupid; public String getGroupid() { return groupid; } public void setGroupid(String groupid) { this.groupid = groupid; } }
映射文件.xml
<!-- 查询用户列表 根据用户名称和用户性别查询用户列表 -->
<select id="findUserList" parameterType="queryVo" resultType="user">
select id,username username_ from user
<!-- where自动将第一个and去掉 -->
<where>
<!-- 这里调用 queryVo的getUser方法获 取user的值 -->
<if test="user!=null">
<!-- 这里调用 queryVo的user的getUsername方法获取username的值 -->
<if test="user.username!=null and user.username!=''">
and user.username = #{user.username}
</if>
<if test="user.sex!=null and user.sex!=''">
and user.sex = #{user.sex}
</if>
</if>
<if test="ids!=null">
<foreach collection="ids" item="id" open="AND ("
separator="OR" close=")">
id =#{id}
</foreach>
<!-- AND id IN (10,89,16) -->
<!-- <foreach collection="ids" item="id" open="AND id IN ("
separator="," close=")">
#{id}
</foreach> -->
</if>
</where>
</select>
2.3、 传递hashmap
parameterType指定 hashmap传递输入参数,#{}和${}中引用map的key。Sql映射文件定义如下:
<!-- 传递hashmap综合查询用户信息 -->
<select id="selectUserByHashmap" parameterType="hashmap" resultType="user">
select * from user where id=#{id} and username like '%${username}%'
</select>
(三)、 resultType输出映射到java对象上
1、返回pojo
resultType:将sql查询结果集映射为java对象。要求sql查询的字段名和resultType指定pojo的属性名一致,才能映射成功。如果全部字段和pojo的属性名不一致,映射生成 的java对象为空,只要有一个字段和pojo属性名一致,映射生成
的java对象不为空。
结论:sql查询字段名和pojo的属性名一致才能映射成功。
不管select返回的是单个 对象还是集合对象,resultType要指定单条记录映射的java对象。
2、返回简单类型
如果 sql查询的结果集只有一行且一列,resultType可以返回简单类型。3、 返回hashmap
输出pojo对象可以改用hashmap输出类型,将输出的字段名称作为map的key,value为字段值。l Mapper.xml
<select id="findUserListReturnMap" parameterType="queryVo" resultType="hashmap">
select id,username username_ from user where username = #{user.username} and sex=#{user.sex}
</select>
l Mapper.java
Public Map findUserListReturnMap(QueryVo queryVo);
建议不使用map作为返回值 ,因为需要对key在代码中硬编码。
(四)、mybatis的动态sql
Mybatis提供 了很多标签,用于拼接sql语句。
if标签
where标签
set标签
foreach标签
<?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="cn.itcast.mybatis.mapper.UserMapperCustom">
<!-- sql片段 -->
<!--
用户查询条件
id:在namespace唯 一标识
建议以单表抽取查询条件
-->
<sql id="query_user_where">
<!-- 这里调用 queryVo的getUser方法获 取user的值 -->
<if test="user!=null">
<!-- 这里调用 queryVo的user的getUsername方法获取username的值 -->
<if test="user.username!=null and user.username!=''">
and user.username = #{user.username}
</if>
<if test="user.sex!=null and user.sex!=''">
and user.sex = #{user.sex}
</if>
</if>
<if test="ids!=null">
<!-- 根据传入id数组构造查询条件 -->
<!-- AND (id =10 OR id =89 OR id=16) -->
<!-- 遍历ids数组
collection:集合,ids数组
item:遍历的每个对象
open:开始遍历时拼接的sql
separator:遍历的间隔符号
close:结束 遍历时拼接的sql
-->
<foreach collection="ids" item="id" open="AND ("
separator="OR" close=")">
id =#{id}
</foreach>
<!-- AND id IN (10,89,16) -->
<!-- <foreach collection="ids" item="id" open="AND id IN ("
separator="," close=")">
#{id}
</foreach> -->
</if>
</sql>
<!-- 定义resultMap,将用户查询的字段和user这个pojo的属性名作一个对应关系 -->
<!--
type:最终映射的java对象。
id:resultMap的唯一标识
-->
<resultMap type="user" id="userListResultMap">
<!-- id标签:查询结果集的唯 一标识 列(主键或唯 一标识 )
column:sql查询字段名(列名)
property:pojo的属性名
result标签:普通列
-->
<id column="id_" property="id"/>
<result column="username_" property="username"/>
<result column="birthday_" property="birthday"/>
</resultMap>
<!-- 查询用户列表 根据用户名称和用户性别查询用户列表 -->
<select id="findUserList" parameterType="queryVo" resultType="user">
select id,username username_ from user
<!-- where自动将第一个and去掉 -->
<where>
<!--
refid:指定 sql片段的id,如果要引用其它命名空间的sql片段,需要前边加namespace
-->
<include refid="query_user_where"/>
</where>
</select>
<!-- 查询用户列表 根据用户名称和用户性别查询用户列表 -->
<select id="findUserListResultMap" parameterType="queryVo" resultMap="userListResultMap">
select id id_,username username_,birthday birthday_ from user
<!-- where自动将第一个and去掉 -->
<where>
<!--
refid:指定 sql片段的id,如果要引用其它命名空间的sql片段,需要前边加namespace
-->
<include refid="query_user_where"/>
</where>
</select>
<!-- 查询用户列表总数 用于分页查询 -->
<select id="findUserCount" parameterType="queryVo" resultType="int">
select count(*) from user
<!-- where自动将第一个and去掉 -->
<where>
<!--
refid:指定 sql片段的id,如果要引用其它命名空间的sql片段,需要前边加namespace
-->
<include refid="query_user_where"/>
</where>
</select>
</mapper>
具体代码示例,看上面两个项目的代码吧!
相关文章推荐
- 深入了解MyBatis返回值
- 深入了解MyBatis参数
- Mybatis学习---了解Mybatis
- MyBatis 入门到精通(一) 了解MyBatis获取SqlSession
- Mybatis深入了解(四)----输入输出映射
- 通过项目逐步深入了解Mybatis<三>
- 深入了解MyBatis返回值
- 深入了解MyBatis二级缓存
- 通过项目逐步深入了解Mybatis
- 深入了解MyBatis返回值
- Mybatis深入了解(五)----动态SQL
- 深入了解mybatis二级缓存
- 通过项目逐步深入了解Mybatis(四)
- Mybatis(三)、mybatis执行示例和mybatis事务以及缓存跟二级缓存简单了解
- mybatis二级缓存了解下
- MyBatis入门——了解基本概念
- Mybatis深入了解(六)----关联查询(高级映射)
- mybatis深入了解
- 通过项目逐步深入了解Mybatis<一>
- MyBatis之简单了解Plugin