Mybatis内容记录

MyBatis

  MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
  MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
  Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

? Mybatis架构

? 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作为输出日志信息

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方法

 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类的所有字段,只需要定义用户的信息字段即可,如下图:

? 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接口添加方法,如下图:

? 测试方法:
在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 }

测试结果如下图:

定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。

? 方法二:使用resultMap
使用resultMap,定义专门的resultMap用于映射一对一查询结果。

? 改造pojo类
在Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
改造Order如下图:

? 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>

? Mapper接口
编写UserMapper如下图:

? 测试方法

 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 }

测试效果如下图:

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

? 修改pojo类
在User类中加入List<Order> orders属性,如下图

? 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接口

? 测试方法

 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 }

测试效果如下图:

时间: 2024-10-08 18:05:25

Mybatis内容记录的相关文章

struts2,json,ajax整合内容记录

使用ssh三大框架整合时关于struts2,json,ajax整合内容记录.这里写主要部分代码 action部分: 注意事项,action部分的返回值要有set和get方法,否则会报错. package com.hcj.action; import net.sf.json.JSONObject; import com.hcj.dto.User; import com.hcj.service.UserService; import com.opensymphony.xwork2.ActionSup

Cs231n课堂内容记录-Lecture3

Lecture 3 课程内容记录:(上)https://zhuanlan.zhihu.com/p/20918580?refer=intelligentunit (中)https://zhuanlan.zhihu.com/p/20945670?refer=intelligentunit (下)https://zhuanlan.zhihu.com/p/21102293?refer=intelligentunit 1.线性分类器(linear classifer): 我们总是希望得到一个函数f(x,w

Cs231n课堂内容记录-Lecture 6 神经网络一

Lecture 6 神经网络一 课程内容记录: (上)https://zhuanlan.zhihu.com/p/21462488?refer=intelligentunit (下)https://zhuanlan.zhihu.com/p/21513367?refer=intelligentunit 1.视频弹幕中关于课堂例子的解释: 1:我们通过学习训练集得到权重W1,对应于可以识别一些feature的模板. 2:输入新的数据X,结合W1,计算得到一个得分score(中间过程可能会再经过一些非线

Cs231n课堂内容记录-Lecture 7 神经网络二

Lecture 7 神经网络二 课程内容记录:https://zhuanlan.zhihu.com/p/21560667?refer=intelligentunit 1.协方差矩阵: 协方差(Covariance)在概率论和统计学中用于衡量两个变量的总体误差.而方差是协方差的一种特殊情况,即当两个变量是相同的情况. 协方差表示的是两个变量的总体的误差,这与只表示一个变量误差的方差不同. 如果两个变量的变化趋势一致,也就是说如果其中一个大于自身的期望值,另外一个也大于自身的期望值,那么两个变量之间

mybatis学习记录

转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加一条,其实大家可以看官方的教程更好些:http://mybatis.github.io/mybatis-3/,而且如果英文不是很好的那就看中文的:http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html) 写在这个系列前面的话: 以前曾经用过ibat

mybatis学习记录------2

一  单条记录查询 上篇博客的例子便是单条记录查询 二 多条记录查询 1 在映射文件中加入如下sql查询,${}:表示拼接sql串,将接收到的参数不加任何修饰拼接在sql中,${value}:接收输入参数的内容,如果传入类型是简单类型,${}中只能使用value. <!--根据名称查找记录,可能返回多条记录 resultType:指定就是单条记录所映射的java对象类型 ${}:表示拼接sql串,将接收到的参数不加任何修饰拼接在sql中. 使用${}拼接sql,容易引起sql注入 ${value

MyBatis 配置文件记录

概念 将数据库表中记录的数据查询出来,并封装成一个实体类的对象. SqlSession代表和数据库的一次会话,是用openSession对象实现的,用完必须关闭,释放资源. SqlSession和connection一样都是非线程安全的,每次使用都应该获取新的对象. mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象. 1  初级的mybatis 拥有两个配置文件:全局配置文件 和 映射文件,必须创建mybatis环境.这里用IDEA创建maven项目,只需要在相应的PO

Mybatis学习记录(六)----Mybatis的高级映射

作者:余家小子 1.一对多查询 1.1 需求 查询订单及订单明细的信息. 1.2 sql语句 确定主查询表:订单表 确定关联查询表:订单明细表 在一对一查询基础上添加订单明细表关联即可. SELECT orders.*, USER.username, USER.sex, USER.address, orderdetail.id orderdetail_id, orderdetail.items_id, orderdetail.items_num, orderdetail.orders_id FR

Maven 搭建SpringMvc+Spring+Mybatis详细记录

总觉得,看比人写的总是那么好,每次搭建框架时都会找博客,找教程来跟着一步一步走,虽然很快搭建成功了,但是经常情况是我并不知道我干了什么,也不记得具体步骤,到底为什么要这么做,今天我详细记录了一下自己搭建的过程,并且尽量理解每一步干什么. SSM框架当下比较流行,我也是用这个框架来作为记录,尝试详细地记录下每一个步骤,学习,不要怕开头难. 一.创建一个新的Maven项目 1. new -> Maven -> Maven Project 选择webapp工程. 2.maven项目建好以后,工程目录