zoukankan      html  css  js  c++  java
  • 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中,配置延迟加载

  • 相关阅读:
    我认知的javascript之函数调用
    table 的宽度设置无效
    【转】微信读书排版引擎自动化测试方案
    RocksDB原理及应用
    ElasticSearch 架构及应用简介
    芝加哥大学论文写作指南 简述
    python 常用模块
    Flask-SQLAlchemy安装及设置
    selenium设置程序失败后重启
    获取临时IP加入临时列表使用
  • 原文地址:https://www.cnblogs.com/Jeremy95-Sze/p/13048941.html
Copyright © 2011-2022 走看看