mybatis技术总结

一、框架概述

day1

1.什么是框架
框架是系统的可重用设计,是对J2EE底层技术的封装(JDBC,IO流,多线程,Servlet,Socket)。

2.框架解决了哪些问题?
1.解决了技术整合问题
在JavaEE体系中,有着各式各样的技术,不同的软件企业,根据自身的业务需求选择不同的技术,容易造成应用依赖技术,增加了项目开发 的复杂性和技术风险性。企业项目中应该将应用的设计与实现技术解耦。
2.解决提升开发效率的问题
企业项目中使用框架,程序员不再需要重复造轮子,只需要专注实现业务需求,使用框架的方便性,提高开发效率
3.解决了稳定性的问题
一个成熟的框架,经过了众多企业项目的验证使用,稳定性有保证
3.J2EE项目的分层:
web层(表现层)-业务层(service)-持久层(dao)

 

二、总结jdbc开发的问题

1.jdbc开发步骤:
加载驱动
创建数据库连接对象
定义sql语句
创建Statement语句对象
设置参数
执行
处理结果集
释放资源

2.jdbc案例程序
第一步:创建项目
第二步:配置pom.xml,导入数据库驱动包
第三步:编写案例代码

 1 public class JdbcTest01 {
 2 
 3 public static void main(String[] args) {
 4 Connection connection=null;
 5 PreparedStatement statement=null;
 6 ResultSet resultSet=null;
 7 //1.创建jdbc驱动
 8 try {
 9 Class.forName("com.mysql.jdbc.Driver");
10 //2.新建连接
11 connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mybatistest", "root", "root");
12 // //3.书写sql
13 String sql="SELECT * FROM USER WHERE id =?";
14 //4.创建预处理对象
15 statement = connection.prepareStatement(sql);
16 //5.获得结果集对象,设置参数
17 statement.setInt(1,1);
18 //6.执行查询
19 resultSet = statement.executeQuery();
20 
21 while (resultSet.next()){
22 System.out.println("用户的id为:"+resultSet.getInt("id")+"用户名:"+resultSet.getString("username"));
23 
24 }
25 } catch (Exception e) {
26 e.printStackTrace();
27 }finally {
28 //7.关闭对象
29 try {
30 
31 if (resultSet!=null) resultSet.close();
32 
33 if (statement!=null) statement.close();
34 if (connection!=null) connection.close();
35 }catch (Exception e){
36 e.printStackTrace();
37 }
38 }
39 
40 }
41 }

 

3.总结jdbc开发的问题
1.频繁创建数据库连接对象和释放,容易造成系统资源的浪费,从而影响系统的性能,在企业中,可以通过使用连接池技术解决这个问题,但是使用jdbc需要我们自己来实现连接池,mybatis内部提供连接池
2.sql语句的定义,参数设计,结果集处理存在硬编码,在企业中sql语句因为需求的变化,所以变化频繁,一但发生变化,需要修改java代码,系统需要重新编译,重新发布,不好维护
3.结果集处理存在重复代码,每次都要遍历resultset结果集,获取一行数据,封装为对象处理麻烦,如果可以自动把行数据封装为java对象这样就方便多了


三、mybatis框架快速入门

1.入门程序实现步骤分析:
第一步:创建Maven项目
第二步:配置pom.xml,导入依赖包

mysql驱动包
mybatis框架包
log4j日志包

第三步:编写主配置文件(sqlMapConfig.xml)

第四步:编写用户实体类
第五步:编写用户dao接口
第六步:编写用户dao接口的映射文件(建立java对象与sql语句的对应关系)

第七步:在主配置文件sqlMapConfig.xml中,加载接口配置文件


第八步:编写测试代码

 1 public class MybatisDemo {
 2 
 3 public static void main(String[] args) {
 4 
 5 SqlSession session=null;
 6 InputStream inputStream =null;
 7 try {
 8 //1.加载读取主配置文件
 9 inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
10 //2.构建新建sqlsessionfatory的必要条件
11 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
12 //根据配置文件创建sqlsessionfatory
13 SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
14 //3.根据sqlsessionfactory创建session
15 session = sqlSessionFactory.openSession();
16 
17 //4.根据session创建dao代理对象
18 UserDao userDao = session.getMapper(UserDao.class);
19 // System.out.println(userDao.getClass());
20 
21 //5.通过dao代理对象执行sql操作数据库数据
22 List<User> userList = userDao.selectAllUser();
23 for (User user:userList){
24 System.out.println(user);
25 }
26 
27 
28 } catch (IOException e) {
29 e.printStackTrace();
30 }finally {
31 try {
32 //6.释放资源
33 session.close();
34 inputStream.close();
35 } catch (IOException e) {
36 e.printStackTrace();
37 }
38 }
39 }
40 }

 

四、mybatis框架介绍
mybatis是Apache软件基金会下的一个开源项目,前身是Ibatis框架。2010年这个项目由apache 软件基金会迁移到google code下,改名为mybatis。2013年11月又迁移到了github(https://github.com/mybatis/mybatis-3/releases)。
mybatis是一个持久层的框架,是对jdbc操作数据库的封装,使开发者只需要关注业务本身,不需要花费精力去处理加载驱动、创建数据库连接对象、创建statement语句对象、参数设置、结果集处理等一系列繁杂的过程代码。
mybatis框架通过xml或注解进行配置,将java对象与sql语句中的参数自动映射生成最终执行的sql语句,并将sql语句执行结果自动映射成java对象。

三句话概括介绍:
1. mybatis框架早期版本叫做Ibatis,目前源代码托管在github
2. mybatis框架是对jdbc操作数据库的封装,是一个持久层的框架
3. mybatis框架通过xml或者注解进行配置,实现java对象与sql语句的自动对应关系(orm映射)

 


五、自定义mybatis框架

1.解析配置文件
1.1.编写Mapper类:namespace名称空间,id属性值,resultType返回值,执行的sql语句
1.2.编写Configuraton类型:连接数据库的四个基本要素,数据源对象(c3p0),接口映射文件


线程安全:
SqlSessionFactory:线程安全,因为它是只读的
SqlSession:线程不安全
两个用户:
用户一:SqlSession新增用户记录,操作时间很久。。。。。

用户二:SqlSession新增订单记录,很快就执行完,并且提交事务。

 

day2

一、mybatis框架实现CRUD操作

1.搭建mybatis框架环境:
第一步:创建maven项目
第二步:配置pom.xml,导入依赖包
mybatis框架包
mysql数据库驱动包
junit测试包
log4j日志包
第三步:编写配置文件(sqlMapConfig.xml)
sqlMapConfig.xml
dao接口映射文件
log4j.properties
加载dao接口映射文件
2.实现根据用户id查询用户:
第一步:编写用户实体类
第二步:编写用户dao(mapper)接口
第三步:编写用户dao(mapper)接口映射文件

第四步:在sqlMapConfig.xml,加载dao接口映射文件

根据用户Id查询用户,说明:
3.实现根据用户名称模糊查询用户:
第一步:声明mapper接口方法
第二步:配置mapper映射文件
第三步:测试

4.新增用户:
4.1.事务(增删改):事务的四个基本特性(ACID)
原子性,一致性,隔离性,持久性

4.2.事务提交方式:
手动提交
自动提交
4.3.注册成为一个网站的用户
用户id是自动增长,不需要传递
网站要给我分配权限,需要使用用户id
要不要查询出这个id值?答案是要

4.4如何获取数据库维护的主键值?

5.根据用户id修改用户:
第一步:声明mapper接口方法
第二步:配置mapper映射文件
第三步:测试

6.根据用户id删除用户:
第一步:声明mapper接口方法
第二步:配置mapper映射文件
第三步:测试

 

二、mybatis框架输入输出映射

1.ParameterType输入映射(参数)
java简单类型
pojo类型

pojo包装类型:就是在pojo中包含了其它的pojo,通常用于接收综合查询条件

第一步:编写pojo包装类型实体类
第二步:声明mapper接口方法
第三步:配置mapper映射文件
第四步:测试

2.ResultType返回值输出

3.ResultMap返回值输出

需求:查询全部订单表数据
需求实现:
编写订单实体类
编写订单mapper接口
编写订单mapper映射文件

在sqlMapConfig.xml加载订单mapper映射文件

 

三、mybatis框架持久层开发的两种方法

1.mapper代理开发方法【重点掌握-记住开发的原则】

2.传统的dao开发方法【了解】
第一步:编写mapper映射文件
第二步:编写dao接口
第三步:编写dao接口实现类

第四步:测试


四、mybatis框架注意事项
1.占位符#{}与字符串拼接符${}区别【重点】
(1).占位符 #{}
当参数传递的是java简单类型(八种基本类型+字符串String)的时候,花括号中的内容可以是任意字符串
(2).字符串拼接符${}
当参数传递的是java简单类型(八种基本类型+字符串String)的时候,花括号中的内容只能是value
(3).#{}、${}当参数传递的pojo类型的时候,花括号中的内容都是pojo的属性

2.
id:唯一标识名称,与接口方法名称一致
parameterType:输入参数类型,与接口方法形参类型一致
resultType:
返回值类型(暂时注意:它是po类的全限定名称),与接口方法返回值类型一致,如果是List<User>,这种返回形式,则直接返回User
#{id}:占位符,相当于jdbc中的问号

获取数据库维护的主键值
selectKey:
作用:查询数据库维护的主键值
属性:
keyColumn:主键字段
keyProperty:实体类中的属性(与主键字段对应)
resultType:主键数据类型
resultMap:用于配置实体类属性与数据库表字段一一对应的
type:要映射的java对象类型
id:唯一标识名称,通过id引用该resultMap

order:在insert语句执行前,还是执行后获取主键值。BEFORE:在insert执行前;AFTER:在insert语句执行后
说明:直接在insert标签中增加属性的方式,只适合于支持自动增长主键类型的数据库,比如mysql。
3.注意事项:java程序代码执行成功,但是数据库中并没有新增记录。原因是没有提交事务,在对数据库的更新操作中(增、删、改)要求提交事务。
自动提交的特点,只要操作一完成,立即提交。如果在同一个方法中,有多个数据库操作,需要使用手动提交的方式。
(方式一)创建SqlSession,指定自动提交事务。true:自动提交;false:不提交。默认是false

 1 SqlSession sqlSession = sqlSessionFactory.openSession(true); 
(方式二)手动提交事务
sqlSession.commit();
4 mapper代理开发方法【掌握】
从入门程序开始,一直使用的方式,即mapper代理开发的方法。特点:
1. 在开发的时候,只需要编写持久层的接口,和持久层接口映射文件(mapper映射文件)。
2. 在执行的时候,mybatis框架通过动态代理生成接口的代理对象。
3. 总结mapper代理开发原则【记住】
1. mapper映射文件中namespace属性值,必须是mapper接口的全限定名称
2. mapper映射文件中sql语句标签的声明,与mapper接口中接口方法声明一致
2.1.sql语句标签中resultType属性指定的返回值类型,与mapper接口方法返回值类型一致。(如果接口方法返回的是集合list,则resultType指定的是list中存放的类型)
2.2.sql语句标签中的id属性值,与mapper接口方法名称一致
2.3.sql语句标签中的parameterType属性指定的类型,与mapper接口方法的形参类型一致

 

 day3

一、mybaits连接池
1.JNDI:java的名称服务,用于从容器中获取数据库的连接(tomcat)
2.POOLED:使用连接池技术
3.UNPOOLED:不使用连接池技术(相当于原生的jdbc操作)


二、mybatis事务控制

1.手动提交
2.自动提交

3.mybatis框架的事务,底层都还是jdbc的事务操作

三、mybatis动态sql

1.动态sql案例(需求:根据用户名称和性别查询用户)
1.声明mapper接口方法
2.配置mapper映射文件

2.if标签
作用:判断传入的参数情况,拼装sql语句片段

 1 <!--根据用户名称和性别查询用户-->
 2 <select id="findUserByNameAndSex"parameterType="user"resultType="user">
 3 select * from `user`
 4 where <!--username like #{username} and sex=#{sex}-->
 5 <!--if:判断用户名称不为空,且不为空字符串,则作为查询条件-->
 6 <if test="username !=null and username !=''">
 7 username like #{username}
 8 </if>
 9 <!--if:判断用户性别不为空,且不为空字符串,则作为查询条件-->
10 <if test="sex !=null and sex !=''">
11 and sex=#{sex}
12 </if>
13 </select>

 

3.where标签
作用:
1.相当于sql语句中的where关键字
2.根据传入的参数情况,智能的去掉多余的and,or关键字
3.根据传入的参数情况,智能的去掉多余的where关键字

 1 <!--根据用户名称和性别查询用户-->
 2 <select id="findUserByNameAndSex"parameterType="user"resultType="user">
 3 select * from `user`
 4 <!-- where username like #{username} and sex=#{sex}-->
 5 <where>
 6 <!--if:判断用户名称不为空,且不为空字符串,则作为查询条件-->
 7 <if test="username !=null and username !=''">
 8 username like #{username}
 9 </if>
10 <!--if:判断用户性别不为空,且不为空字符串,则作为查询条件-->
11 <if test="sex !=null and sex !=''">
12 and sex=#{sex}
13 </if>
14 </where>
15 
16 </select>

 

4.set标签:
作用:
1.相当于sql语句中的set关键字
2.根据传入的参数情况,智能的去掉最后一个多余的逗号

 1 <!-- 动态修改用户数据 -->
 2 <update id="dynamicUpdateUser"parameterType="user">
 3 update `user`
 4 <!-- set username='小李飞刀',sex='2' where id=2 -->
 5 <set>
 6 <if test="username != null and username !=''">
 7 username=#{username},
 8 </if>
 9 <if test="sex != null and sex !=''">
10 sex=#{sex},
11 </if>
12 </set>
13 
14 <where>
15 id=#{id}
16 </where>
17 </update>

5.sql(include)标签:

作用:
1.提取公共的sql语句片段

 1 <!--sql:提取公共的sql语句片段,说明:
 2 id:唯一标识名称,通过id引用该sql片段
 3 -->
 4 <sql id="select_orders_list">
 5 o.id,o.user_id,o.number,o.createtime,o.note
 6 </sql>
 7 
 8 <!--查询全部订单数据,使用resultType实现-->
 9 <select id="findAllOrders"resultType="cn.itheima.po.Orders">
10 <!--include:引用sql语句片段,说明:
11 refid:sql语句片段的id属性值
12 -->
13 select <include refid="select_orders_list"></include> from orders o
14 </select>

6.foreach标签:

作用:
1.循环处理参数集合(list,数组)

 1 <!-- 批量新增用户-->
 2 <insert id="batchAddUsers"parameterType="list">
 3 insert into `user`(username,birthday,sex,address)
 4 values
 5 <!-- foreach:循环处理参数集合
 6 collection:参数集合,这里是list(固定写法)
 7 item:当前遍历的对象
 8 separator:指定分割符
 9 -->
10 <foreach collection="list"item="u"separator=",">
11 (#{u.username},#{u.birthday},#{u.sex},#{u.address})
12 </foreach>
13 <!-- ('用户1','2018-07-08','1','地址1'),('用户2','2018-07-08','1','地址2') -->
14 </insert>

四、mybatis关联查询

1.关联关系分类:
一对一关联关系:人和身份证关系,【双向的】一对一关系
一对多关联关系:用户和订单的关系
多对多关联关系:用户和角色

2.分析用户订单数据模型:
第一步:先确定单表有什么字段
第二步:找出关联字段
第三步:结合业务需求确定表的关系

3.一对一关联查询:
实现思路:
第一步:编写sql语句
第二步:声明mapper接口方法
第三步:配置mapper映射文件

通过ResultType实现:
关键步骤:编写一个实体类,包含sql语句中的字段对应属性

 

通过ResultMap实现(<association/>):
关键步骤:在实体类之间建立关系,建立订单到用户的一对一关系

<!-- 配置订单到用户的一对一关联关系,说明:
type:要映射的类型
id:唯一标识名称,通过id引用该resultMap
-->
<resultMap type="orders"id="ordersUsersResultMap">
<!-- 配置订单主键字段对应关系 -->
<id column="id"property="id"/>
<!-- 配置订单的普通字段对应关系 -->
<result column="user_id"property="userId"/>
<result column="number"property="number"/>
<result column="createtime"property="createtime"/>
<result column="note"property="note"/>

<!-- association:配置一对一关联关系,说明:
property:要映射的属性名称
javaType:要映射的属性类型(必须要指定)
-->
<association property="user"javaType="User">
<!-- 配置用户的主键字段对应关系 -->
<id column="user_id"property="id"/>
<!-- 配置用户的普通字段对应关系 -->
<result column="username"property="username"/>
<result column="address"property="address"/>
</association>

</resultMap>

<!-- 查询全部订单数据,并且关联查询订单所属的用户数据(resultMap)-->
<select id="findAllOrdersAndUserResultMap"resultMap="ordersUsersResultMap">
SELECT
o.id,
o.user_id,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
orders o
LEFT JOIN `user` u ON o.user_id = u.id
</select>

 

4.一对多关联查询:
实现思路:
第一步:编写sql语句
第二步:声明mapper接口方法
第三步:配置mapper映射文件

思考题:一对多能不能使用ResultType实现? 不能使用ResultType实现

使用ResultMap实现(<collection/>):
关键步骤:在实体类之间建立关系,建立用户到订单的一对多关系

<!-- 配置用户到订单的一对多关联关系,说明:
type:要映射的类型
id:唯一标识名称,通过id引用该resultMap
-->
<resultMap type="user"id="usersOrdersResultMap">
<!-- 配置用户的主键字段对应关系 -->
<id column="id"property="id"/>
<!-- 配置用户的普通字段对应关系 -->
<result column="username"property="username"/>
<result column="birthday"property="birthday"/>
<result column="sex"property="sex"/>
<result column="address"property="address"/>

<!-- collection:配置一对多关联关系,说明:
property:要映射的属性名称
javaType:要映射的属性类型(可以指定,可以不指定,建议都指定)
ofType:指定集合中存放的类型(必须要指定)
-->
<collection property="ordersList"javaType="List"ofType="Orders">
<!-- 配置订单的主键对应关系 -->
<id column="oid"property="id"/>
<!-- 配置订单普通字段对应关系 -->
<result column="number"property="number"/>
<result column="createtime"property="createtime"/>
</collection>

</resultMap>

<!-- 查询全部用户数据,并且关联查询出用户的所有订单数据 -->
<select id="findAllUsersAndOrders"resultMap="usersOrdersResultMap">
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
o.id oid,
o.number,
o.createtime
FROM
`user` u
LEFT JOIN orders o ON u.id = o.user_id
</select>

 

5.多对多关联查询:通过中间表看成两个一对多关联关系

需求:查询用户数据,并且关联查询出用户的角色数据

实现思路:
第一步:编写sql语句
第二步:声明mapper接口方法
第三步:配置mapper映射文件

关键步骤:在实体类之间建立关系,建立用户到角色的一对多关系

<!-- 配置用户到角色的一对多关联关系,说明:
type:要映射的类型
id:唯一标识名称,通过id引用该resultMap
-->
<resultMap type="user"id="usersRolesResultMap">
<!-- 配置用户的主键字段对应关系 -->
<id column="id"property="id"/>
<!-- 配置用户的普通字段对应关系 -->
<result column="username"property="username"/>
<result column="birthday"property="birthday"/>
<result column="sex"property="sex"/>
<result column="address"property="address"/>

<!-- collection:配置一对多关联关系,说明:
property:要映射的属性名称
javaType:要映射的属性类型(可以指定,可以不指定,建议都指定)
ofType:指定集合中存放的类型(必须要指定)
-->
<collection property="roleList"javaType="List"ofType="Role">
<!-- 配置订单的主键对应关系 -->
<id column="role_id"property="roleId"/>
<!-- 配置订单普通字段对应关系 -->
<result column="role_name"property="roleName"/>
</collection>

</resultMap>

<!-- 查询用户数据,并且关联查询用户的所有角色数据-->
<select id="findUsersAndRoles"resultMap="usersRolesResultMap">
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
r.role_id,
r.role_name
FROM
`user` u
INNER JOIN user_role ur ON u.id = ur.user_id
INNER JOIN role r ON ur.role_id = r.role_id
</select>

day4


一、mybatis延迟加载

1.什么是延迟加载?
延迟加载,叫做懒加载,按需加载。
它的特点关联查询中,分步骤实现查询(每一步都是单表操作)

2.延迟加载案例演示:
查询订单数据,并且关联查询出订单所属的用户数据。采用延迟加载的方式实现。
实现步骤:
第一步:只从订单表查询订单数据
第二步:在需要的时候,在查询用户表的数据
第三步:配置mybatis框架,开启延迟加载


延迟加载的注意事项:toString方法和debug调试模式看不到延迟加载的效果

3.一对多关联查询的延迟加载方式实现:
第一步:单表查询用户数据
第二步:在需要的时候,再查询订单表的数据
第三步:配置mybatis框架,开启延迟加载


二、mybatis缓存

1.一级缓存:sqlSession范围的缓存,一级缓存本身就已经存在,不需要关心

2.二级缓存:mapper级别级别,在多个sqlSession之间可以共享数据
第一步:需要配置sqlMapConfig.xml,开启二级缓存
第二步:序列化Seriallizable,实体类对象需要实现序列化
第三步:在mapper映射文件,还需要明确是否使用缓存

说明:mybatis的二级缓存只做了解,在企业项目中不推荐使用。原因是mybatis的缓存
不能实现【细粒度】的控制。实际项目中我们会考虑使用像redis中间件


三、mybatis注解开发【了解】

1.注解基本操作(CRUD操作):
查询:@Select
修改:@Update
删除:@Delete
新增:@Insert

获取数据库维护的主键值:
@SelectKey

 

2.注解高级操作(关联查询):
@Results注解:相当于xml文件中的<ResultMap/>标签
@Result注解:相当于<ResultMap/>的子标签<id/>和<result/>
@One注解:配置一对一关联关系,相当于xml中的<association/>,可以实现延迟加载
@Many注解:配置一对多关联关系,相当于xml中的<collection/>标签,可以实现延迟加载

延迟加载方式实现:一对一关联查询的方式:
实现步骤:
第一步:只从订单表查询数据
第二步:在需要的时候,查询用户表数据
第三步:在sqlMapConfig.xml中,配置延迟加载

 

延迟加载方式实现:一对多关联查询:
需求:查询全部用户数据,并且关联查询出用户的全部订单数据。采用延迟加载的方式实现
实现步骤:
第一步:只查询用户表数据
第二步:在需要的时候,查询订单表的数据
第三步:在sqlMapConfig.xml中,配置延迟加载

 

posted @ 2020-06-05 12:02  JAVA_宇  阅读(838)  评论(0编辑  收藏  举报