Mybatis内容记录

 

 

 

 

MyBatis

  MyBatis 本是apache的一个开源项目iBatis,
二〇一〇年这一个体系由apache software foundation 迁移到了google
code,并且改名为MyBatis 。二〇一三年10月搬迁到Github。

  MyBatis是一个理想的持久层框架,它对jdbc的操作数据库的经过进展打包,使开发者只需要关怀
SQL
本身,而不需要花费精力去处理例如登记驱动、创造connection、创造statement、手动设置参数、结果集检索等jdbc繁杂的经过代码。

  Mybatis通过xml或声明的法门将要执行的各个statement(statement、preparedStatemnt、CallableStatement)配置起来,并经过java对象和statement中的sql举办映射生成最后实施的sql语句,最终由mybatis框架执行sql并将结果映射成java对象并回到。


Mybatis架构

 

MyBatis 1


mybatis配置

  SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行条件等音讯。
  mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

通过mybatis环境等配置音讯构造SqlSessionFactory即会话工厂


由会话工厂创造sqlSession即会话,操作数据库需要经过sqlSession举办。


mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是主导执行器、一个是缓存执行器。

⦁ Mapped
Statement也是mybatis一个底层封装对象,它包裹了mybatis配置音讯及sql映射音信等。

  **mapper.xml文件中一个sql对应一个MappedStatement对象,sql的id即是Mappedstatement的id。**


**
MappedStatement对sql执行输入参数举行定义,包括HashMap、基本类型、pojo,Executor通过MappedStatement在实施sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
MappedStatement对sql执行输出结果举办定义,包括HashMap、基本项目、pojo,Executor通过MappedStatement在履行sql后将出口结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的剖析处理过程。**

 

mybatis默认使用log4j作为出口日志信息

 

MyBatis 2MyBatis 3

1 # Global logging configuration
2 log4j.rootLogger=DEBUG, stdout
3 # Console output...
4 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
5 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
6 log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

log4j.properties

 

⦁ #{}和${}
#{}表示一个占位符号,通过#{}可以兑现preparedStatement向占位符中设置值,自动举行java类型和jdbc类型转换。#{}可以有效预防sql注入。
#{}可以接收简单类型值或pojo属性值。
固然parameterType传输单个简单类型值,#{}括号中可以是value或任何名称。

${}表示拼接sql串,通过${}能够将parameterType
传入的情节拼接在sql中且不举办jdbc类型转换,
${}可以吸纳简单类型值或pojo属性值,即使parameterType传输单个简单类型值,${}括号中只可以是value。


parameterType和resultType

  parameterType:指定输入参数类型,mybatis通过ognl从输入对象中收获参数值拼接在sql中。
  resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定项目标对象。假如有多条数据,则分别展开映射,并把目标放置容器List中


selectOne和selectList

  selectOne查询一条记下,借使利用selectOne查询多条记下则抛出分外:**org.apache.ibatis.exceptions.TooManyResultsException**

  selectList可以查询一条或多条记下。


namespace

  mybatis官方推荐应用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以应用pojo包装对象或map对象,保证dao的通用性。

SqlMapConfig.xml中布局的情节和一一如下:

properties(属性)**settings(全局配置参数)typeAliases(类型别名)typeHandlers(类型处理器)objectFactory(对象工厂)plugins(插件)**

environments(环境集合属性对象)**environment(环境子属性对象)***transactionManager(事务管理)*dataSource(数据源)***mappers(映射器)*

  •  mappers(映射器)Mapper配置的两种方法:**
  • *<mapper resource=” ”
    />  **采用相对于类路径的资源(现在的使用方法)  **如:<mapper
    resource=”sqlmap/User.xml” />***

  • <mapper class=” ”
    />  
    利用mapper接口类路径  *
    如:<mapper
    class=”cn.tzy.mybatis.mapper.UserMapper”/>*

   注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个索引中。

  • <package
    name=””/>  
    登记指定包下的拥有mapper接口  *
    如:<package
    name=”cn.tzy.mybatis.mapper”/>*

*   ***注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个索引中。*** ***

 

 

 ⦁
mysql自增主键再次来到

 1 <!-- 保存用户 -->
 2 <insert id="saveUser" parameterType="com.tzy.mybatis.pojo.User">
 3     <!-- selectKey 标签实现主键返回 -->
 4     <!-- keyColumn:主键对应的表中的哪一列 -->
 5     <!-- keyProperty:主键对应的pojo中的哪一个属性 -->
 6     <!-- order:设置在执行insert语句前执行查询id的sql,还是在执行insert语句之后执行查询id的sql -->
 7     <!-- resultType:设置返回的id的类型 -->
 8     <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int">
10         SELECT LAST_INSERT_ID()
11     </selectKey>
12     INSERT INTO user
13     (username,birthday,sex,address) VALUES
14     (#{username},#{birthday},#{sex},#{address})
15 </insert>
16 
17 //LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

 

⦁ Mysql使用
uuid实现主键

 1 <!-- 保存用户 -->
 2 <insert id="saveUser" parameterType="com.tzy.mybatis.pojo.User">
 3     <!-- selectKey 标签实现主键返回 -->
 4     <!-- keyColumn:主键对应的表中的哪一列 -->
 5     <!-- keyProperty:主键对应的pojo中的哪一个属性 -->
 6     <!-- order:设置在执行insert语句前执行查询id的sql,还是在执行insert语句之后执行查询id的sql -->
 7     <!-- resultType:设置返回的id的类型 -->
 8     <selectKey keyColumn="id" keyProperty="id" order="BEFORE" resultType="string">
10         SELECT LAST_INSERT_ID()
11     </selectKey>
12     INSERT INTO `user`
13     (username,birthday,sex,address) VALUES
14     (#{username},#{birthday},#{sex},#{address})
15 </insert>
16 
17 //注意这里使用的order是“BEFORE”

 


mybatis与hibernate不同

Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编排Sql语句。mybatis可以经过XML或表明格局灵活配置要运行的sql语句,并将java对象和sql语句映射生成最后实施的sql,最终将sql执行的结果再映射生成java对象。

Mybatis学习窍门低,简单术数,程序员间接编写原生态sql,可严谨控制sql执行性能,灵活度高,非凡适合对关周详据模型要求不高的软件开发,例如互联网软件、集团营业类软件等,因为这类软件需要变化频繁,一但需求转变要求成果输出快捷。可是灵活的前提是mybatis不可能做到数据库无关性,尽管需要实现帮助多种数据库的软件则需要自定义多套sql映射文件,工作量大。

Hibernate对象/关系映射能力强,数据库无关性好,对于涉嫌模型要求高的软件(例如需要稳定的定制化软件)假如用hibernate开发可以省去成千上万代码,提升成效。可是Hibernate的上学窍门高,要了解门槛更高,而且怎么设计O/R映射,在性质和目的模型之间什么权衡,以及哪些用好Hibernate需要具备很强的经历和能力才行。
总的说来,按照用户的需要在少数的资源条件下一旦能做出维护性、扩大性突出的软件架构都是好架构,所以框架只有顺应才是最好。 

 

标签使用:

if标签

 1 <!-- 根据条件查询用户 -->
 2 <select id="queryUserByWhere" parameterType="user" resultType="user">
 3 SELECT id, username, birthday, sex, address FROM `user`
 4 WHERE 1=1
 5 <if test="sex != null and sex != ''">
 6 AND sex = #{sex}
 7 </if>
 8 <if test="username != null and username != ''">
 9 AND username LIKE
10 "%"#{username}"%"
11 </if>
12 </select>
13 
14 //注意字符串类型的数据需要要做不等于空字符串校验。

 

 

where标签

 

地点的sql还有where 1=1
这样的说话,很麻烦

可以选择where标签举行改建

 1 <!-- 根据条件查询用户 -->
 2 <select id="queryUserByWhere" parameterType="user" resultType="user">
 3 SELECT id, username, birthday, sex, address FROM `user`
 4 <!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
 5 <where>
 6 <if test="sex != null">
 7 AND sex = #{sex}
 8 </if>
 9 <if test="username != null and username != ''">
10 AND username LIKE
11 '%${username}%'
12 </if>
13 </where>
14 </select>


Sql片段

 

Sql中可将再一次的sql提取出来,使用时用include引用即可,最后达到sql重用的目标。

 

把下边例子中的id, username, birthday, sex,
address提取出来,作为sql片段,如下:

<!-- 根据条件查询用户 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
<!-- SELECT id, username, birthday, sex, address FROM `user` -->
<!-- 使用include标签加载sql片段;refid是sql片段id -->
SELECT <include refid="userFields" /> FROM `user`
<!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 -->
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</where>
</select>


<!-- 声明sql片段 -->
<sql id="userFields">
id, username, birthday, sex, address
</sql>

设若要动用其它Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace

 


foreach标签

 

向sql传递数组或List,mybatis使用foreach解析,如下:

 

依照五个id查询用户音讯
查询sql:
SELECT *
FROM user WHERE id IN (1,10,24)

 

一般来说图在pojo中定义list属性ids存储六个用户id,并添加getter/setter方法

MyBatis 4

 1 UserMapper.xml添加sql,如下:
 2 <!-- 根据ids查询用户 -->
 3 <select id="queryUserByIds" parameterType="queryVo" resultType="user">
 4     SELECT * FROM `user`
 5     <where>
 6         <!-- foreach标签,进行遍历 -->
 7         <!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
 8         <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
 9         <!-- open:在前面添加的sql片段 -->
10         <!-- close:在结尾处添加的sql片段 -->
11         <!-- separator:指定遍历的元素之间使用的分隔符 -->
12         <foreach collection="ids" item="item" open="id IN (" close=")" separator=",">
14             #{item}
15         </foreach>
16     </where>
17 </select>

测试方法如下:

@Test
public void testQueryUserByIds() {
    // mybatis和spring整合,整合之后,交给spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper执行根据条件查询用户
    QueryVo queryVo = new QueryVo();
    List<Integer> ids = new ArrayList<>();
    ids.add(1);
    ids.add(10);
    ids.add(24);
    queryVo.setIds(ids);

    List<User> list = userMapper.queryUserByIds(queryVo);

    for (User u : list) {
        System.out.println(u);
    }

    // mybatis和spring整合,整合之后,交给spring管理
    sqlSession.close();
}

 


关联查询

  ** 商品订单数据模型**

⦁ 一对一询问
需求:查询所有订单音信,关联查询下单用户消息。

留意:因为一个订单音信只会是一个人下的订单,所以从询问订单信息出发关联查询用户音信为一对一询问。假使从用户音讯出发查询用户下的订单音信则为一对多询问,因为一个用户可以下多少个订单


方法一:使用resultType

接纳resultType,改造订单pojo类,此pojo类中包括了订单音信和用户音讯
这样回去对象的时候,mybatis自动把用户信息也注入进来了
⦁ 改造pojo类
OrderUser类继承Order类后OrderUser类包括了Order类的具备字段,只需要定义用户的音信字段即可,如下图:

MyBatis 5

⦁ Mapper.xml
在UserMapper.xml添加sql,如下

<!-- 查询订单,同时包含用户数据 -->
<select id="queryOrderUser" resultType="orderUser">
SELECT
o.id,
o.user_id
userId,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
`order` o
LEFT JOIN `user` u ON o.user_id = u.id
</select>

 

⦁ Mapper接口
在UserMapper接口添加方法,如下图:

MyBatis 6

⦁ 测试方法:
在UserMapperTest添加测试方法,如下:

 1 @Test
 2 public void testQueryOrderUser() {
 3 // mybatis和spring整合,整合之后,交给spring管理
 4 SqlSession sqlSession = this.sqlSessionFactory.openSession();
 5 // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
 6 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 7 
 8 // 使用userMapper执行根据条件查询用户
 9 List<OrderUser> list = userMapper.queryOrderUser();
10 
11 for (OrderUser ou : list) {
12 System.out.println(ou);
13 }
14 
15 // mybatis和spring整合,整合之后,交给spring管理
16 sqlSession.close();
17 }

测试结果如下图:

MyBatis 7

概念专门的pojo类作为出口类型,其中定义了sql查询结果集所有的字段。此办法较为简单,公司中行使大规模。

 

 


方法二:使用resultMap

应用resultMap,定义专门的resultMap用于映射一对一询问结果。

⦁ 改造pojo类
在Order类中插手User属性,user属性中用来存储关联查询的用户音讯,因为订单关联查询用户是一对一关系,所以这里运用单个User对象存储关联查询的用户音信。
改造Order如下图:

MyBatis 8

⦁ Mapper.xml
这里resultMap指定orderUserResultMap,如下:

 1 <resultMap type="order" id="orderUserResultMap">
 2 <id property="id" column="id" />
 3 <result property="userId" column="user_id" />
 4 <result property="number" column="number" />
 5 <result property="createtime" column="createtime" />
 6 <result property="note" column="note" />
 7 
 8 <!-- association :配置一对一属性 -->
 9 <!-- property:order里面的User属性名 -->
10 <!-- javaType:属性类型 -->
11 <association property="user" javaType="user">
12 <!-- id:声明主键,表示user_id是关联查询对象的唯一标识-->
13 <id property="id" column="user_id" />
14 <result property="username" column="username" />
15 <result property="address" column="address" />
16 </association>
17 
18 </resultMap>
19 
20 <!-- 一对一关联,查询订单,订单内部包含用户属性 -->
21 <select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
22 SELECT
23 o.id,
24 o.user_id,
25 o.number,
26 o.createtime,
27 o.note,
28 u.username,
29 u.address
30 FROM
31 `order` o
32 LEFT JOIN `user` u ON o.user_id = u.id
33 </select>

MyBatis, 

 

⦁ Mapper接口
编写UserMapper如下图:

MyBatis 9

⦁ 测试方法

 1 @Test
 2 public void testQueryOrderUserResultMap() {
 3     // mybatis和spring整合,整合之后,交给spring管理
 4     SqlSession sqlSession = this.sqlSessionFactory.openSession();
 5     // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
 6     UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 7 
 8     // 使用userMapper执行根据条件查询用户
 9     List<Order> list = userMapper.queryOrderUserResultMap();
10 
11     for (Order o : list) {
12         System.out.println(o);
13     }
14 
15     // mybatis和spring整合,整合之后,交给spring管理
16     sqlSession.close();
17 }

测试效果如下图:

MyBatis 10

 

 


一对多询问

案例:查询所有用户音信及用户关联的订单音信。
用户信息和订单音信为一对多关系。

⦁ 修改pojo类
在User类中插足List<Order> orders属性,如下图

MyBatis 11

⦁ Mapper.xml
在UserMapper.xml添加sql,如下:

 1 <resultMap type="user" id="userOrderResultMap">
 2     <id property="id" column="id" />
 3     <result property="username" column="username" />
 4     <result property="birthday" column="birthday" />
 5     <result property="sex" column="sex" />
 6     <result property="address" column="address" />
 7 
 8     <!-- 配置一对多的关系 -->
 9     <collection property="orders" javaType="list" ofType="order">
10         <!-- 配置主键,是关联Order的唯一标识 -->
11         <id property="id" column="oid" />
12         <result property="number" column="number" />
13         <result property="createtime" column="createtime" />
14         <result property="note" column="note" />
15     </collection>
16 </resultMap>
17 
18 <!-- 一对多关联,查询订单同时查询该用户下的订单 -->
19 <select id="queryUserOrder" resultMap="userOrderResultMap">
20     SELECT
21     u.id,
22     u.username,
23     u.birthday,
24     u.sex,
25     u.address,
26     o.id oid,
27     o.number,
28     o.createtime,
29     o.note
30     FROM
31     `user` u
32     LEFT JOIN `order` o ON u.id = o.user_id
33 </select>

⦁ Mapper接口

MyBatis 12

⦁ 测试方法

 1 @Test
 2 public void testQueryUserOrder() {
 3     // mybatis和spring整合,整合之后,交给spring管理
 4     SqlSession sqlSession = this.sqlSessionFactory.openSession();
 5     // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
 6     UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 7 
 8     // 使用userMapper执行根据条件查询用户
 9     List<User> list = userMapper.queryUserOrder();
10 
11     for (User u : list) {
12         System.out.println(u);
13     }
14 
15     // mybatis和spring整合,整合之后,交给spring管理
16     sqlSession.close();
17 }

测试效果如下图:

 MyBatis 13

 

网站地图xml地图