MyBatis使用大全(4)------XML映射文件配置
来源:互联网 发布:数控铣削编程与加工 编辑:程序博客网 时间:2024/06/03 21:55
MyBatis真正的强大,在于其映射语句的魔力。
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
(1)cache 给定命名空间的配置缓存。(2)cache-ref 其他命名空间缓存配置的引用。
(3)resultMap 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象
(4)sql 可被其他语句引用的可重用语句块。
(5)insert 映射插入语句
(6)update 映射更新语句
(7)delete 映射删除语句
(8)select 映射查询语句
在我们描述每个元素细节之前,我们先感受一些元素的使用实例,
以下实例分为UserMainMapper.XML配置的XML版本和java注解版本,
也可以根据实际情况两种都用,但是同名方法只能用XML或java注解,
先不多少,看实例,这里将入门体验文章做简化,分析元素。
一,准备条件
--jar
mybatis-3.2.2.jar --mybatisjar
ojdbc6.jar --数据库驱动,这个地方用的是oracle,而入门体验中用的是Mysql,所以驱动不一样
junit-4.4.jar --单元测试
--数据库表
--建表CREATE TABLE t_user_main( f_id NUMBER(3) PRIMARY KEY, f_username VARCHAR(4), f_age NUMBER(3));--设置主键自增长CREATE SEQUENCE user_sequenceINCREMENT BY 1 -- 每次加几个START WITH 1 -- 从1开始计数NOMAXVALUE -- 不设置最大值NOCYCLE -- 一直累加,不循环--插入测试数据INSERT INTO t_user_main(f_id,f_username,f_age)VALUES(1,'one',25);INSERT INTO t_user_main(f_id,f_username,f_age)VALUES(2,'two',25);COMMIT;--查询SELECT * FROM t_user_main;
二,项目结构
三,test-jdbc.properties和mybatis-config.xml配置
test-jdbc.properties:
jdbc.driver=oracle.jdbc.driver.OracleDriverjdbc.url=jdbc:oracle:thin:@localhost:1521/XEjdbc.username=systemjdbc.password=123456
mybatis-config:
<?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) --><properties resource="test-jdbc.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="autoMappingUnknownColumnBehavior" value="WARNING"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="defaultFetchSize" value="100"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/></settings> --><!-- 别名(typeAliases) --><!-- <typeAliases><typeAlias alias="User" type="com.lanhuigu.mybatis.entity.User"/></typeAliases> --><!-- environments环境*environment 环境变量 *transactionManager 事务管理器*dataSource 数据源 --> <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><!-- mappers映射器 --><mappers><!-- <mapper resource="com/lanhuigu/mybatis/map/UserMainMapper.xml"/> --><package name="com.lanhuigu.mybatis.map"/></mappers></configuration>
四,User.java,UserMainMapper.java接口和UserMainMapper.xml配置(Mapper)
User.java
package com.lanhuigu.mybatis.entity;import java.io.Serializable;public class User implements Serializable{private static final long serialVersionUID = -3412068097348759984L;private Integer id;private String username;private Integer age;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}}
UserMainMapper.java(接口)
package com.lanhuigu.mybatis.map;import java.util.List;import java.util.Map;import org.apache.ibatis.annotations.Delete;import org.apache.ibatis.annotations.Insert;import org.apache.ibatis.annotations.Options;import org.apache.ibatis.annotations.Param;import org.apache.ibatis.annotations.Select;import org.apache.ibatis.annotations.Update;import com.lanhuigu.mybatis.entity.User;public interface UserMainMapper {//=======================XML版=======================/** * 查询用户对象--返回User对象 */public User queryUserMainById(int id);/** * 查询用户对象--返回多个--List<User> */public List<User> queryUserMainList();/** * 查询用户对象--返回map */public Map<String,Object> queryUserMainResultMap(int id);/** * 查询用户对象--返回多个--List<Map<String,Object>> */public List<Map<String,Object>> queryUserMainResultListMap();/** * 插入用户对象 */public int insertUser(User user);/** * 更新用户对象 */public int updateUser(User user);/** * 删除用户对象 */public int deleteUser(int id);//=======================注解版==========================/** * 查询用户对象--返回User对象 */@Select(" select f_id id,f_username username,f_age age from t_user_main where f_id = #{id} ")@Options(flushCache=true)public User queryUserMainByIdNew(@Param("id") int id);/** * 查询用户对象--返回多个--List<User> */@Select("select f_id id,f_username username,f_age age from t_user_main ")@Options(flushCache=true)public List<User> queryUserMainListNew();/** * 查询用户对象--返回map */@Select("select f_id id,f_username username,f_age age from t_user_main where f_id = #{id}")@Options(flushCache=true)public Map<String,Object> queryUserMainResultMapNew(@Param("id") int id);/** * 查询用户对象--返回多个--List<Map<String,Object>> */@Select("select f_id id,f_username username,f_age age from t_user_main")@Options(flushCache=true)public List<Map<String,Object>> queryUserMainResultListMapNew();/** * 插入用户对象 */@Insert("insert into t_user_main (f_id,f_username,f_age) "+ " values(#{id},#{username},#{age}) ")@Options(useGeneratedKeys=false)public int insertUserNew(User user);/** * 更新用户对象 */@Update("update t_user_main set f_username=#{username},f_age=#{age} "+ " where f_id=#{id} ")public int updateUserNew(User user);/** * 删除用户对象 */@Delete("delete from t_user_main where f_id=#{id}")@Options(flushCache=true)public int deleteUserNew(@Param("id") int id);}
UserMainMapper.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="com.lanhuigu.mybatis.map.UserMainMapper"> <!-- 查询用户对象,返回User对象 --> <select id="queryUserMainById" parameterType="int" flushCache="true" resultType="com.lanhuigu.mybatis.entity.User"> select f_id id, f_username username, f_age age from t_user_main where f_id = #{id} </select> <!-- 查询用户对象,返回list<User> --> <select id="queryUserMainList" flushCache="true" resultType="com.lanhuigu.mybatis.entity.User"> select f_id id, f_username username, f_age age from t_user_main </select> <!-- 查询用户对象,返回Map --> <select id="queryUserMainResultMap" parameterType="int" flushCache="true" resultType="java.util.HashMap"> select f_id id, f_username username, f_age age from t_user_main where f_id = #{id} </select> <!-- 查询用户对象,返回List<Map<String,Object>> --> <select id="queryUserMainResultListMap" flushCache="true" resultType="java.util.HashMap"> select f_id id, f_username username, f_age age from t_user_main </select> <!-- 插入用户对象(insert) --> <insert id="insertUser" parameterType="com.lanhuigu.mybatis.entity.User" useGeneratedKeys="false"> insert into t_user_main (f_id,f_username,f_age) values(#{id},#{username},#{age}) </insert> <!-- 更新用户对象(update) --> <update id="updateUser" parameterType="com.lanhuigu.mybatis.entity.User" flushCache="true"> update t_user_main set f_username=#{username},f_age=#{age} where f_id=#{id} </update> <!-- 删除用户对象(delete) --> <delete id="deleteUser" parameterType="int" flushCache="true"> delete from t_user_main where f_id=#{id} </delete> </mapper>
五,测试代码
package com.lanhuigu.mybatis;import java.io.InputStream;import java.util.List;import java.util.Map;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 com.lanhuigu.mybatis.entity.User;import com.lanhuigu.mybatis.map.UserMainMapper;public class MyBatisTest {@Testpublic void testMyBatis() {String resource = "mybatis-config.xml";SqlSessionFactory sqlSessionFactory = null;SqlSession session = null;try {//读取资源文件InputStream is = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);session = sqlSessionFactory.openSession();//mapper调用UserMainMapper userMainMapper = session.getMapper(UserMainMapper.class);//================XML测试=================//查询--select--返回User对象User user = userMainMapper.queryUserMainById(1);System.out.println("user="+user);System.out.println(user.getUsername());//查询--select--返回多个User对象--List<User>/*List<User> list = userMainMapper.queryUserMainList();for(int i=0;i<list.size();i++ ){User user = list.get(i);System.out.println(user.getUsername());}*///查询--select--返回map/*Map<String,Object> userMap = userMainMapper.queryUserMainResultMap(1);System.out.println("userMap="+userMap);System.out.println(userMap.get("USERNAME"));*///查询--select--返回List<Map<String,Object>>/*List<Map<String,Object>> list = userMainMapper.queryUserMainResultListMap();System.out.println("ListMap="+list);for (int i=0;i<list.size();i++) {Map<String,Object> userMap = list.get(i);System.out.println(userMap.get("USERNAME"));}*///插入--insert/*User user = new User();user.setId(3);user.setUsername("three");user.setAge(25);int result = userMainMapper.insertUser(user);if (result > 0) {System.out.println("添加用户成功");//事务提交session.commit();} else {System.out.println("添加用户失败");//事务回滚session.rollback();}*///更新--update/*User user = new User();user.setId(3);user.setUsername("this three update");user.setAge(25);int result = userMainMapper.updateUser(user);if (result > 0) {System.out.println("更新成功");//事务提交session.commit();} else {System.out.println("更新失败");//事务回滚session.rollback();}*///删除--delete/*int result = userMainMapper.deleteUser(3);if (result > 0) {System.out.println("删除成功");//事务提交session.commit();} else {System.out.println("删除失败");//事务回滚session.rollback();}*///=================注解测试===================/* * 只需将xml测试代码copy一份,然后将方法名都加上一个New即可 * 在UserMainMapper.java映射器中原本可以将xml部分注释, * 注解部分方法用同名,但是这样做我们就得将UserMainMapper.xml删掉, * 或者改名,否则注解不能查询出数值,着跟命名空间和class,xml加载有关系. * 总之class中和xml中不能出现注解和xml同时使用,对于单个方法,二者 * 只能存在其一,否则mybatis不知道你到底想干啥,只能什么都不做了 *///eg./*User user = userMainMapper.queryUserMainByIdNew(1);System.out.println("user="+user);System.out.println(user.getUsername());*/} catch (Exception e) {if (session != null) {session.close();}}}}
有了上面的体验,我们在对每个元素等等进行分析,然后在参考实例,能体验更深。
结合上面的实例对元素进行分析和补充。
select元素
查询语句是MyBatis中最常用的元素,作为一个持久层框架,把数据放入数据库是一个方面,
把数据取一条或多条更是重中之重。简单查询语句:
<select id="queryUserMainById" parameterType="int" flushCache="true" resultType="com.lanhuigu.mybatis.entity.User"> select f_id id, f_username username, f_age age from t_user_main where f_id = #{id} </select>
这个语句称之为queryUserMainById,接受一个int或Integer的参数,
返回一个com.lanhuigu.mybatis.entity.User的对象,这个如果嫌写起来长,
可以在mybatis-config.xml中配置别名,这个地方直接用别名替代。
别名配置:
<typeAliases><typeAlias alias="User" type="com.lanhuigu.mybatis.entity.User"/></typeAliases>select语句中参数id符号:
#{id}获取传入的参数。
这样MyBatis处理时底层用JDBC生产预编译语句,JDBC底层MyBatis替我们做了,
这样我们只需关注MyBatis的应用,避免写大量的JDBC代码,提高工作效率,调用时直接执行。
select元素有很多属性可供选择,如下:
<select id="queryUserMainById" parameterType="int" parameterMap="deprecated" resultType="hashmap" resultMap="userMainResultMap" flushCache="false" useCache="true" timeout="10000" fetchSize="256" statementType="PREPARED" resultSetType="FORWARD_ONLY">select元素相关属性的描述,如下:
insert,update和delete元素
数据插入(insert),数据更新(update),数据删除(delete)实现大同小异。例如:
<span style="color:#000000;"><!-- 插入用户对象(insert) --> <insert id="insertUser" parameterType="com.lanhuigu.mybatis.entity.User" useGeneratedKeys="false"> insert into t_user_main (f_id,f_username,f_age) values(#{id},#{username},#{age}) </insert> <!-- 更新用户对象(update) --> <update id="updateUser" parameterType="com.lanhuigu.mybatis.entity.User" flushCache="true"> update t_user_main set f_username=#{username},f_age=#{age} where f_id=#{id} </update> <!-- 删除用户对象(delete) --> <delete id="deleteUser" parameterType="int" flushCache="true"> delete from t_user_main where f_id=#{id} </delete></span>这三个元素的属性描述如下:
sql元素
发
这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。
它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化。
把上面的实例中UserMainMapper.xml修改,来个简单实例:
<!-- sql语句块 --> <sql id="queryConditionSql"> f_id = #{id} </sql> <!-- 查询用户对象,返回User对象 --> <select id="queryUserMainById" parameterType="int" flushCache="true" resultType="com.lanhuigu.mybatis.entity.User"> select f_id id, f_username username, f_age age from t_user_main <where> <include refid="queryConditionSql"/> </where> </select>将查询语句的条件由where f_id=#{id}修改成sql语句块替代。
这样整个xml中条件部分共同的地方都提出来,避免重复啰嗦。
当然,sql语句块除了可以用于条件部分,还可以用于其它任地方,
比如:
<!-- sql语句块 --> <sql id="queryConditionSql"> f_id = #{id} </sql> <sql id="att"> f_username username, f_age age </sql> <!-- 查询用户对象,返回User对象 --> <select id="queryUserMainById" parameterType="int" flushCache="true" resultType="com.lanhuigu.mybatis.entity.User"> select f_id id, <include refid="att"/> from t_user_main <where> <include refid="queryConditionSql"/> </where> </select>查询时,效果一样。
总结:
(1)sql语句块用于提出xml共同sql
(2)sql语句块可以置于xml文件中查询语句前后,位置无关系,都能调用。
参数(parameters)
但是
MyBatis的参数功能是非常强大的,前面用到的sql中,如果parameterType="int"
只是进行一个简单的整数传入,但是,在插入语句中,我们传入的是类型User对象:
<insert id="insertUser" parameterType="com.lanhuigu.mybatis.entity.User" useGeneratedKeys="false"> insert into t_user_main (f_id,f_username,f_age) values(#{id},#{username},#{age}) </insert>
如果 User 类型的参数对象传递到了语句中,id、username 和 password 属性将会被查找,然后将它们的值传入预处理语句的参数中。
这点对于向语句中传参是比较好的而且又简单,不过参数映射的功能远不止于此。
首先,像 MyBatis 的其他部分一样,参数也可以指定一个特殊的数据类型。
#{property,javaType=int,jdbcType=NUMERIC}
像 MyBatis 的剩余部分一样,javaType 通常可以从参数对象中来去确定,前提是只要对象不是一个 HashMap。那么 javaType 应该被确定来保证使用正确类型处理器。
NOTE 如果 null 被当作值来传递,对于所有可能为空的列,JDBC Type 是需要的。你可以自己通过阅读预处理语句的 setNull() 方法的 JavaDocs 文档来研究这种情况。
为了以后定制类型处理方式,你也可以指定一个特殊的类型处理器类(或别名),比如:
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
尽管看起来配置变得越来越繁琐,但实际上是很少去设置它们。
对于数值类型,还有一个小数保留位数的设置,来确定小数点后保留的位数。
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
最后,mode 属性允许你指定 IN,OUT 或 INOUT 参数。如果参数为 OUT 或 INOUT,参数对象属性的真实值将会被改变,就像你在获取输出参数时所期望的那样。如果 mode 为 OUT(或 INOUT),而且 jdbcType 为 CURSOR(也就是 Oracle 的 REFCURSOR),你必须指定一个 resultMap 来映射结果集到参数类型。要注意这里的 javaType 属性是可选的,如果左边的空白是 jdbcType 的 CURSOR 类型,它会自动地被设置为结果集。
#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}
MyBatis 也支持很多高级的数据类型,比如结构体,但是当注册 out 参数时你必须告诉它语句类型名称。比如(再次提示,在实际中要像这样不能换行):
#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}
尽管所有这些强大的选项很多时候你只简单指定属性名,其他的事情 MyBatis 会自己去推断,最多你需要为可能为空的列名指定 jdbcType。
#{firstName}#{middleInitial,jdbcType=VARCHAR}#{lastName}
<insert id="addUser" parameterType="com.lanhuigu.core.dao.model.user.User" useGeneratedKeys="true" keyColumn="f_userId" flushCache="true">insert into t_user_main (f_userId , f_userName , f_email , f_password , f_isPayPassword , f_mobile , f_registerTime , f_role , f_status , f_realAuth , f_redInviteCode, f_redBeInviteCode, f_version )values(#{userId,jdbcType=VARCHAR},#{userName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{isPayPassword,jdbcType=VARCHAR},#{mobile,jdbcType=VARCHAR},#{registerTime,jdbcType=VARCHAR},#{roles,jdbcType=VARCHAR},#{status,jdbcType=VARCHAR},#{realAuth,jdbcType=VARCHAR},#{redInviteCode,jdbcType=VARCHAR},#{redBeInviteCode,jdbcType=VARCHAR},#{version,jdbcType=VARCHAR})</insert>
字符串替换
在上面中,很多地方用到#{},默认情况下,使用#{}格式的语法会导致 MyBatis 创建预处理语句属性并安全地设置值(比如?)。
这样做更安全,更迅速,通常也是首选做法,不过有时你只是想直接在 SQL 语句中插入一个不改变的字符串,
或者在条件放一个字符串。比如:
f_id = ${id}
以这种方式接受从用户输出的内容并提供给语句中不变的字符串是不安全的,
会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并检验。
- MyBatis使用大全(4)------XML映射文件配置
- MyBatis使用大全(4)------XML映射文件配置
- MyBatis使用大全(3)------XML映射文件配置
- mybatis 生成映射文件generatorConfig.xml配置
- mapper.xml映射文件配置 mybatis
- Mybatis XML映射文件
- Mybatis--XML映射文件
- MyBatis对应xml映射文件l配置例子
- mabatis 的映射文件mybatis-mapper.xml配置
- MyBatis之XML文件配置实现映射器Mapper
- mybatis的xml映射文件**
- mybatis之XML映射文件
- MyBatis之使用XML配置SQL映射(一)
- MyBatis的XML映射文件、映射器
- MyBatis之使用XML配置SQL映射(二)CRUD映射配置
- mybatis映射器文件配置
- MyBatis Spring整合配置映射接口类与映射xml文件
- MyBatis Spring整合配置映射接口类与映射xml文件
- 多线程基础
- MyBatis官方教程及源码解析——mapper映射文件
- 划分树算法 模板
- STL源码剖析-序列式容器之deque
- 51Nod-1275-连续子段的差异
- MyBatis使用大全(4)------XML映射文件配置
- Java中synchronize 与lock实现多线程同步
- poj 2104 K-th Number (划分树模板题)
- 25 岁的 Linux 已经无处不在,它是如何毁了微软统治世界的计划?
- html 轮播图
- codeforces] ECR19 A. k-Factorization [数论]
- 使用commons的Configuration读取XML
- linux运维-虚拟机的创建,快照
- 使用mybatis自带工具,自动生成表对应domain、mapper.xml以及dao