mybatis课堂笔记

二次信任 提交于 2020-03-03 05:07:16

mybatis第一章:基于知识
1.三层架构:
复习mvc: 做web开发常用的架构
m是数据–是通过service-访问dao-访问数据库获取数据。
v是视图–一般使用jsp,html显示m中的数据,用户可以看到视图
c是控制器–使用servlet, 控制器调用service,把数据选择一个视图显示

三层架构:做任何应用都可以使用。三层可以延伸为6层,9层。
把应用的类和功能在逻辑上分层不同的部分, 每个部分完成自己的功能,和其他部分关联小。

第一层:视图层,一般使用jsp,html表示的,作用是接收用户的请求,并显示处理结果数据
第二层:业务层,主要是service包中的类,处理业务逻辑的。
第三层:持久层(数据访问层),主要是dao包中的类,访问数据库的,处理数据的。

2.框架(framework)
概念1: 整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;
另一种认为,框架是可被应用开发者定制的应用骨架、模板

注意:1)框架是可重用的,在多个不同的项目中使用框架
2)框架中有定义好的对象,以及对象之间的调用,可以完成一定的功能。

概念2:框架就是一个软件,软件里面写好了一些功能。这些功能是软件的一些类相互调用完成的。
我们的项目可以在框架之上加入自己的逻辑功能,就能利用框架提供的功能完成项目的开发。

      用户发起请求---你的程序代码---访问了框架(执行了一些操作,框架把结果交给了你的程序)
      框架帮你实现了部分的功能。
      
      
      框架就是一个舞台,舞台提供了灯光,布景等。 你的程序就看做是演员,在舞台上表演。
      框架是一个辅助功能,框架不是全能的,一个框架只是处理某一个方面的功能。
      
      学习的框架:
       1)mybatis(持久层):是持久层框架,访问数据库的。
       2)spring(业务层):是业务层的框架,处理业务逻辑,事务等使用的。强项不是访问数据库。
       3)springmvc(视图层框架):做web项目使用的,处理用户请求的,不适合访问数据库。

怎么学框架:
1.认识框架,了解他的功能,能干什么
2.学习框架的语法。框架要完成一个功能,是有自己的语法的。
3.需要在项目中使用框架

3.mybatis框架

mybatis原名叫做ibatis,是apache 基金会的项目。是一个持久层框架。
mybatis的源代码是放在github服务器上的。mybatis是开源的

mybatis提供的功能:1. Data Access Objects(DAOs) 2.SQL Maps 
  1.Data Access Objects(数据库访问): mybatis底层可以使用jdbc的功能执行数据库的访问。
                                 实现对数据的增删改查功能,执行sql语句。
                                 
                                 mybatis是jdbc的很好的替代。
                                 

  2.SQL Maps(sql映射) : 执行sql得到ResultSet,mybatis可以把ResultSet中的数据自动转为一个java对象,或一个List集合。
                mybatis帮你实现执行sql于得到java对象,不用自己编写while
  
      完成的功能就是:
        rs = stmt.executeQuery("select * from student");
		while (rs.next()) {
			Student stu = new Student();
			stu.setId(rs.getInt("id"));
			stu.setName(rs.getString("name"));
			stu.setAge(rs.getInt("age"));
			//从数据库取出数据转为 Student 对象,封装到 List 集合
			stuList.add(stu);
		}
		
    sql映射:把数据库表中的数据转为了java对象。
             表中的一行数据对应一个java对象。 表中行数据映射为java对象
             你操作java对象就相当于操作表中的数据

4.mybatis能做什么
1.创建对象,例如Connection , Statement ,ResultSet
2.执行sq语句,把ResultSet转为java 对象
3.关闭资源 conn.close(); stat.close(); rs.close()

以后我们使用mybatis代替jdbc访问数据库,执行sql语句。
mybatis底层使用的还是jdbc的代码,mybatis把常用的操作进行了处理。
内部执行Connection , Statement ,ResultSet对象,sql的执行, 资源的关闭。
这些操作都是自动完成的。不需要开发人员参与。

开发人员作什么:提供要执行的sql语句。

5.资源
1)https://mybatis.org/mybatis-3/zh/index.html 文档
2)https://github.com/mybatis/mybatis-3/releases 下载mybatis的资源

===============================================================================
第二章 mybatis入门
mybatis基本使用, 完成数据库的crud (增删改查)

第一个例子,完成对student表的增删改查。
实现步骤:
1.创建mysql表student(id,name ,email, age), id就是普通列,不是自动增长的。
2.创建maven项目
3.加入maven需要的gav坐标
1)mybatis依赖
2)mysql驱动
3)junit

同时还有加入插件(resource插件,编译插件)
以上内容写入到 pom.xml文件

4.创建实体类Student(要求属性名和列名一样)

5.创建一个dao接口,叫做StudentDao, 接口中定义操作数据库的方法

6.创建mybatis 的sql映射文件。
sql映射文件就是mybatis使用的一个xml文件。
sql映射文件:定义sql语句,mybatis会执行文件中的sql语句

sql映射文件的要求:
1.文件名和dao接口名一样。
2.文件和dao接口在同一目录

sql映射文件:一个表对应一个sql映射文件。 这个文件中写对这个表的sql语句。
一个项目中sql映射文件有多个。

mybatis可以使用xml配置文件(sql映射文件),注解定义sql语句,推荐示意xml配置文件

7.创建mybatis的主配置文件(一个项目中一个)
在resources目录下 创建一个xml文件,写连接数据库的配置信息

8.测试使用mybatis访问数据库。

使用main也可以使用单元测试。测试mybatis的功能点。


使用mybatis实现数据库的操作
1.定义Dao接口,在接口中定义方法。
2.编写mapper文件(sql映射文件),写sql语句
3.创建SqlSessionFactory对象, 通过SqlSessionFactory的 SqlSession session = factory.openSession()
得到SqlSession对象。

4.通过SqlSession的方法执行sql语句
int rows =session.delete(sqlId,1004);
int rows =session.update(sqlId,student);
int rows =session.insert(sqlId,student);
List students =session.selectList(sqlId);


mybatis中主要的类功能说明
1.Resources:读取mybatis主配置文件
2.SqlSessionFactoryBuilder:使用主配置文件的信息创建SqlSessionFactory对象。
创建了SqlSessionFactory对手, 这个Builder类就没什么用了。

3.SqlSessionFactory:重要的。
SqlSessionFactory通过主配置文件,能创建Connection对象, 能够读取sql映射文件的信息
SqlSessionFactory是一个重量级对象, 整个项目中有一个就可以了。 单例

他有重要的方法,这些方法都是获取 SqlSession对象的。
1) openSession():获取一个SqlSession, 非自动提交事务的SqlSession
2) openSession(true): 获取一个自动提交事务的SqlSession
3) openSession(false):和openSession()是一样的。

SqlSessionFactory 是一个接口,mybatis使用的实现类是:DefaultSqlSessionFactory

4.SqlSession重要的
SqlSession是mybatis中的重要对象,负责执行sql语句的。
SqlSession是一个接口,他的实现类DefaultSqlSession。

SqlSession不是线程安全的,在多线程环境下,多个线程使用同一个SqlSession会有问题。不能这么用。
需要的做法是: 在一个方法的内部,在sql开始执行之前使用openSession()获取一个新的SqlSession对象
然后再sql语句之后,关闭SqlSession,执行SqlSession.close()

重要的方法:
1)selectOne:根据主键,或唯一值查询, 执行了sql后是一条或没有记录,多余一条记录是错误
2)selectList:查询结果是多行记录
3)insert:添加
4)update:更新
5)delete:删除
6)commit:事务提交
7)rollback:事务回滚

==================================================================================
mybatis的动态代理技术

/**
* 使用dao对象执行数据库的操作,在dao的方法
* 现在是 调用SqlSession的方法执行sql语句。
* 只有 sqlId的值有变化,
* String sqlId = “com.wkcto.dao.StudentDao.”+“selectStudents”;
* String sqlId = “com.wkcto.dao.StudentDao.”+“insertStudent”;
*
* 现在想根据dao的方法调用例如 dao.selectStudents() 推导出要执行的sql语句的id?
*
* 分析: 要执行的是 List students = dao.selectStudents();
* 1. 调用方法的对象是 dao 就是StudentDao接口。
* 通过dao的接口,能知道接口的全限定名称 com.wkcto.dao.StudentDao
*
* 2. 通过dao.selectStudents()方法名称,我能知道执行 标签的id属性值
* sql的id是 selectStudents
*
* 3. 通过 dao.selectStudents()返回的是List集合,我能知道要执行的sql语句是
* 查询多条记录, mybatis应该能执行 sqlSesison.selectList()返回多条
* mybatis是可以根据返回值知道 是返回一条记录(selectOne()),还是多条记录。
*
* 通过以上信息,首先能得到要执行的sqlId是 接口的全限定名称 + 方法名就可以了
* com.wkcto.dao.StudentDao + “.” + “selectStudents”
* 然后再根据方法的返回值List mybatis就知道要执行 sqlSession.selectList()方法。
*
* mybatis可以动态代理的技术,实现简化对数据库的操作。
* 1)动态代理可以根据接口创建代理对象, 代理对象调用方法,完成一定的功能。
* 2)动态代理要值的功能写在InvocationHandler接口的实现类invoke()方法中。
*
*
* mybatis使用动态代理的技术,创建dao接口的代理对象。
* 通过代理对象执行sql语句,开发人员不需要编写dao接口的实现类。
* mybatis通过dao的方法调用能知道要执行的sql语句id,mybatis内部执行的sql
*
*/

怎么实现动态代理功能
1.删除dao接口的实现类
2.使用SqlSession.getMapper(dao接口的class)
例如 StudentDao dao = SqlSession.getMapper(StudentDao.class);
List students = dao.selectStudents();


mybatis动态代理源代码分析

  1. 代理类型org.apache.ibatis.binding.MapperProxy

  2. 实现了InvocationHandler
    public class MapperProxy implements InvocationHandler {

        //实现了invoke方法
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       	try {
       		if (Object.class.equals(method.getDeclaringClass())) {
       			return method.invoke(this, args);
       		}
    
       		if (this.isDefaultMethod(method)) {
       			return this.invokeDefaultMethod(proxy, method, args);
       		}
       	} catch (Throwable var5) {
       		throw ExceptionUtil.unwrapThrowable(var5);
       	}
    
       	MapperMethod mapperMethod = this.cachedMapperMethod(method);
       	return mapperMethod.execute(this.sqlSession, args);
       	// mapperMethod.execute()在最后执行的是 sqlSession.selectList()
       }
    

    }

上午的重点

  1. 模板创建使用。 mybatis-mapper mybatis-config
  2. mybatis动态代理使用。

mybatis的传入参数:
从java程序中把数据传递到mapper文件中, 在sql语句中可以使用这些参数

1.parameterType:他是一个属性,表示dao接口中方法参数的类型。
parameterType的值可以是 1)类型的全限定名称 2)别名(mybatis已经定义了一些别名,也可以自定义)
parameterType他是可选的,不是必须的。 mybatis通过反射能获取到参数的类型的,所以无需设置。

2.传参数的方式
1)dao的方法只有一个简单类型的参数。在xml文件中占位表示 #{任意字符}
简单类型:java中的基本数据类型和String

  方法定义: Student selectStudentById(Integer stuId);
  mapper文件: select id,name, email,age from student where id=#{studentId}

2)【dao方法中有多个简单类型参数,多余一个参数,每个参数都是简单类型的。】重点
使用@Param的注解, 这个注解是mybatis框架的, 命名参数。 这个命名的参数可以在mapper文件中使用
语法:@Param要放在dao接口方法的形参定义前面 @Param(“自定义参数名”) String name

 方法定义: //多个简单类型的参数
            List<Student> selectStudentByMore(
                                  @Param("pname") String name,
                                  @Param("page") Integer age);

 mapper文件:
            select id,name, email,age from student
            where name=#{pname} or age=#{page}

3)【dao接口中方法的参数是一个自定义对象,可以使用对象的属性名表示参数值】 重点
xml配置文件中的语法: #{属性名,javaType=Java数据类型的全名称,jdbcType=数据库列的类型}
简化的方式: #{属性名} ,mybatis会执行对象的getXXX()方法获取属性值

 方法定义: List<Student> selectByObject(Student student);
 
 mapper文件:
          select id,name, email,age from student
          where name=#{name} or age=#{age}

4)dao方法中的参数是多个简单类型的,使用位置传值, 语法格式: #{arg0}, #{arg1} , arg是关键字,
0,1 参数的位置 ,从0开始

方法定义:List<Student> selectByNameOrAge(String name,Integer age);
mapper文件: select id,name,email, age from student where name =#{arg0} or age =#{arg1}

5)dao方法中参数是Map, 使用map的key表示参数值,语法:#{key}

方法定义: List<Student> selectByMap(Map<String,Object> map);
mapper文件: select id,name, email,age from student
             where name=#{kname} or age=#{kage}
             
使用dao的位置:
    Map<String,Object> map = new HashMap<>();
    map.put("kname","长乐");
    map.put("kage",20);
    List<Student> students = dao.selectByMap(map);

#和$区别
#:推荐使用的, 使用的 ?替代 #{}的值。
当你使用#的时候,mybatis在内部使用PrepareStatement对象执行sql语句
PrepareStatement执行sql语句的优点:
1.执行效率更高,比Statement更高
2.避免sql注入,安全性更高

KaTeX parse error: Expected 'EOF', got '#' at position 7: :使用方式和#̲一样。使用不是使用?,他使用的是字符的连接操作。
select * from student where id=${stuid}

  mybatis执行是 "select * from student where id =" +"'+ 1005 +'";
         内部使用Statement对象执行sql语句的,没有?的使用。
   Statement执行sql语句, 是字符串连接的sql语句,缺点:
     1.执行sql语句的效率不高
     2.有sql注入的风险。
     
     
   例如你的传入的stuid的值是 ”1005;delete from student“
     "select * from student where id =1005; delete from student";
     
   
  $有什么用?
   1.当你的sql中的值,你能确定他是安全的,可以使用$
   2.使用$可以代替表名,列名这样的操作。 你的查询是操作多个表,可以$代替表名。
     此时$表示列名,表名,不是列值。

=======================================================================================
mybatis封装输出结果:mybatis执行sql语句把得到ResultSet如何转为java对象。
1.resultType
resultType 表示sql语句之后,ResultSet转为的java对象。 执行sql把数据封装到java对象中。
mybatis会创建resultType表示的java对象, 把列的值赋给java对象的属性。
赋值规则是:同名的列赋值给同名的属性。

            java对象应该有无参数构造方法, mybatis调用构造方法创建对象。
            java对象属性应该有set、get方法。
        
      resultType的值  
      ①:类型的全限定名称, 例如 com.wkcto.domain.Student
      ②:别名(自定义别名): 就给上面的student类起个简单好记名称
         使用别名的步骤:
          1.在mybatis的主配置文件中定义别名,使用<typeAlias>定义别名
          2.在resultType中使用别名
          
          
          定义别名:
           1)使用typeAlias一次给一个类型定义别名
           <typeAlias type="类型的全限定名称" alias="自定义别名" />
           <typeAlias type="类型的全限定名称" alias="自定义别名" />
           。。。
           
           2)使用<package name=""/>
               name:是包名, 表示这个包中的所有类,他们的类名就是别名,别名不区分大小写
      

     当dao方法的返回List时, sql语句的执行结果可以是多行记录或者没有记录
     当dao方法的返回值不是List时, sql语句的执行结果只能返回一行记录或没有记录

2.resultMap
resultMap叫做结果映射,是更高级的resultType.
使用时机,当你的列名和java对象的属性名不一样时,使用resultMap定义列和属性的关系。

    使用步骤:
     1.使用<resultMap>定义 列名和属性名的对应关系。 指定列的值赋给那个属性
     2.在<select>,<update>,<delete>,<insert>中使用resultMap指定1中定义的关系名称
     
     例子:
     <resultMap id="orderMap" type="com.wkcto.domain.MyOrder">
		<!--定义列名和属性的对应,把指定列值赋给属性-->
		<!--对应主键列,使用id标签,其他列使用result标签-->
		<id column="id" property="id" />
		<result column="name" property="ordername"/>
		<result column="email" property="orderemail" />
		<result column="age" property="ordertime" />
	</resultMap>


	<select id="selectMyOrder" resultMap="orderMap">
		select id,name,email,age from student
	</select>
	
注意:resultType 和 resultMap不能一起使用。
  1. like 查询
    1.在java代码中把 like的组织好, 把这个值传入到sql语句中
    java代码中 String name="%李%";
    sql语句:select id,name,email,age from student where name like #{myname}

2.在mapper中直接组织 like的内容。
语法是 where name like空格"%“空格#{name}空格”%"

================================================================================================
第四章动态sql
什么是动态sql: 使用mybatis的标签在mapper文件中拼接出where条件。
1.if: name是属性名, 判断name的值不是null ,不是“” 为true, true时会把name=#{name}的内容加入到sql语句中

name =#{name}

2.where:能够解决if的一些问题。 where标签说明: 如果在where标签中有一个条件是true,
那么mybatis会在 sql语句后面加入 where 关键字, 如果where标签中没有一个符合条件,不加where
同时where标签还能把不符合要求的 不用的字符去掉。

3.foreach:遍历 。循环list,数组array等。 主要用在in操作中
select * from student where id in (1001,1002,1003)

语法:

#{item的值}

把刚才的List循环写为mybatis

<foreach collection="list" open="(" close=")"
      item="myid" separator=",">
             #{myid}
</foreach>

4.代码片段:
定义一段sql代码, 可以几个字段名, 表名, where条件。
这段代码可以反复使用, 可以重用。

使用步骤:
1.先定义片段,给片段起个名称
2.使用引用片段

==========================================================================================
第五章:配置文件
1.mapper文件:写sql语句的
2.mybatis主配置文件
1)有约束文件 http://mybatis.org/dtd/mybatis-3-config.dtd
2)根标签 configuration
3)主配置文件的内容
1.别名
2.数据源
3.mapper文件位置

3.配置详细说明
1):mybatis的全局配置,影响这个mybatis的运行。
配置的有缓存, 日志等等

2):定义一些变量,在当前的主配置文件中使用。
最常用的是把数据库的url,username,password,driver信息定义在 properties文件中(属性配置文件)

3):配置别名
①:
②:

4) 配置环境,就是数据库连接
表示一个确切的数据库连接信息
transactionManager:配置事务类型
①:JDBC 表示使用jdbc中的Connection处理事务提交,回滚。
②:MANAGED 使用容器管理事务, 就是说mybatis自己不处理事务, 而是交给其他对象处理事务。

      dataSource:数据源,连接数据库
         type:表示数据源的类型,有三个值 POOLED, UNPOOLED, JNDI
         
         UNPOOLED: 这个数据源的实现只是每次被请求时打开和关闭连接,执行一个数据库的操作就创建一个Connection
                    数据库的操作结束,关闭连接。 这种方式Connection使用效率低。 一般是测试环境中使用。
                    
         POOLED: 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。
                  在程序运行时,创建多个Connection对象,执行数据库的操作不关闭Connection。而是重复多次使用Connection对象
                  
         JNDI:  这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
         
 5)<mappers>指定mapper文件位置的(写的sql语句的文件位置)
     ①:使用mapper子标签,一次指定一个mapper文件
      <mapper resource="com/wkcto/dao/StudentDao.xml"/> 
      resource:mapper文件的路径,从类文件所在的根目录开始的    
      
    ②:使用mappers的子标签<package>
      <!--
        name:包名, mapper文件所在的包名。
              mybatis会把这个包中的所有xml文件都找到。加载到mybatis。

         使用package的要求:
          1.mapper文件名称必须和接口名一样,区分大小写的一样
          2.mapper文件比和接口在同一目录
     -->
    <package name="com.wkcto.dao"/>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!