zoukankan      html  css  js  c++  java
  • mybatis

    mybatis

    第一章 介绍
    1. 三层架构
      界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
      业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
      数据访问层: 就是访问数据库, 执行对数据的查询,修改,删除等等的。


    三层对应的包
      界面层: controller包 (servlet)
      业务逻辑层: service 包(XXXService类)
      数据访问层: dao包(XXXDao类)


    三层中类的交互
      用户使用界面层--> 业务逻辑层--->数据访问层(持久层)-->数据库(mysql)


    三层对应的处理框架
      界面层---servlet---springmvc(框架)
      业务逻辑层---service类--spring(框架)
      数据访问层---dao类--mybatis(框架)


    2.框架
      框架是一个舞台, 一个模版

    模版:
      1. 规定了好一些条款,内容。
      2. 加入自己的东西

    框架是一个模块
      1.框架中定义好了一些功能。这些功能是可用的。
      2.可以加入项目中自己的功能, 这些功能可以利用框架中写好的功能。


    框架是一个软件,半成品的软件,定义好了一些基础功能, 需要加入你的功能就是完整的。
    基础功能是可重复使用的,可升级的。

    框架特点:
      1. 框架一般不是全能的, 不能做所有事情
      2. 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
      3. 框架是一个软件

     

    mybatis框架
    一个框架,早期叫做ibatis, 代码在github。
    mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
      1)sql mapper :sql映射
        可以把数据库表中的一行数据 映射为 一个java对象。
        一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据

      2) Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。


    mybatis提供了哪些功能:
      1. 提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了
      2. 提供了执行sql语句的能力, 不用你执行sql
      3. 提供了循环sql, 把sql的结果转为java对象, List集合的能力
        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);
          }
      4.提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet


    开发人员做的是: 提供sql语句
    最后是: 开发人员提供sql语句--mybatis处理sql---开发人员得到List集合或java对象(表中的数据)

    总结:
      mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,
      使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet
      的创建,销毁,sql的执行。

     

    第二章:主要类介绍
    1 主要类的介绍
      1) Resources: mybatis中的一个类, 负责读取主配置文件
          InputStream in = Resources.getResourceAsStream("mybatis.xml");

      2)  SqlSessionFactoryBuilder : 创建SqlSessionFactory对象,
          SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
           //创建SqlSessionFactory对象
           SqlSessionFactory factory = builder.build(in);

      3)SqlSessionFactory : 重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。
        在整个项目中,有一个就够用了。

        SqlSessionFactory:接口 , 接口实现类: DefaultSqlSessionFactory
        SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();

        openSession()方法说明:
        1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
        2. openSession(boolean): openSession(true) 获取自动提交事务的SqlSession.
          openSession(false) 非自动提交事务的SqlSession对象


      4)SqlSession:
        SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
        SqlSession接口的实现类DefaultSqlSession。

      使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。
      在执行完sql语句后,需要关闭它,执行SqlSession.close(). 这样能保证他的使用是线程安全的。

      代码部分 

     1  //测试方法
     2     @Test
     3     public void testInsert() throws IOException {
     4         //访问,mybatis获取student数据
     5         //1.定义mybatis主配置文件的名称,从根目录开始
     6         String config="mybatis.xml";
     7         //读取这个config表示的内容
     8         InputStream in= Resources.getResourceAsStream(config);
     9         //3.创建SqlSessionFactoryBuilder对象
    10         SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
    11         //4,创建SqlSessionFactory对象
    12         SqlSessionFactory factory=builder.build(in);
    13         //5.{重要}获取SqlSession对象,从SqlSessionFactory获取SqlSession
    14         SqlSession sqlSession=factory.openSession();
    15         //6.{重要}执行要执行的sql语句的标识,sql映射文件中的namespace+"."+标识的id
    16         String sqlId="com.rzpt.dao.StudentDao"+"."+"insertstudent";
    17         //7.执行sql语句,通过sqlId找到语句
    18         Student student=new Student();
    19         //student.setId(4);
    20         student.setName("张飞");
    21         student.setEmail("zhangfei@qq.com");
    22         student.setAge(33);
    23         int nums = sqlSession.insert(sqlId,student);
    24 
    25         //mybatis默认不是自动提交事务的,所以在insert,update,delete之后要手动提交事务
    26         sqlSession.commit();
    27         //8.输出结果
    28         System.out.println("执行insert的结果="+nums);
    29         //9.关闭sqlSession
    30         sqlSession.close();
    31     }
    View Code

    第三章:动态代理
    1. 动态代理: 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象
    2. 传入参数: 从java代码中把数据传入到mapper文件的sql语句中。
      1)parameterType : 写在mapper文件中的 一个属性。 表示dao接口中方法的参数的数据类型
        例如StudentDao接口
        public Student selectStudentById(Integer id)

           

      parameterType他的值是java类型数据类型的全限定名称或mybatis定义的别名
       例如:parameterType="java.lang.Integer"
    或: parameterType="int"
        不是强制的,mybatis通过反射可以自己获取,一般不用写

      2) 一个简单类型的参数
      简单类型: mybatis把java的基本数据类型和String都叫简单类型。
      在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}

      接口:public Student selectStudentById(Integer id)
        mapper:select id,name, email,age from student where id=#{studentId}

      3) 多个参数,使用@Param命名参数
      接口 public List<Student> selectMulitParam(@Param("myname") String name, @Param("myage") Integer age)
      使用 @Param("参数名") String name
      mapper文件:
      <select>
        select * from student where name=#{myname} or age=#{myage}
      </select>

      

       

      4) 多个参数,使用java对象
        语法 #{属性名}

        vo: value object , 放一些存储数据的类。比如说 提交请求参数, name ,age
        现在想把name ,age 传给一个service 类。

        vo: view object , 从servlet把数据返回给浏览器使用的类,表示显示结果的类。

        pojo: 普通的有set, get方法的java类。 普通的java对象

        Servlet --- StudentService( addStudent( MyParam param) )

        entity(domain域): 实体类, 和数据库中的表对应的类,

        (1).

    定义方法,多个参数,利用java对象作为方法的参数
    * 使用对象语法:
    * #{属性名,javaType=类型名称,jdbcType=数据类型} 很少用
    * javaType=类型名称,在java中的数据类型
    * jdbcType=数据类型,在数据库的数据类型
    * 例如:#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
    * 简化:#{属性名},上述mybatis反射机制会自动获取,不用提供

         

         

         (2).多个参数-简单类型,按位置查询  

          mybatis.3.4之前,使用#{0},
       mybatis.3.4之后,使用#{arg0},
        

        

         (3).多个参数,使用Map存放多个值

        

         

      5) # 和 $

        select id,name, email,age from student where id=#{studentId}
        # 的结果: select id,name, email,age from student where id=?


        select id,name, email,age from student where id=${studentId}
        $ 的结果:select id,name, email,age from student where id=1001

        String sql="select id,name, email,age from student where id=" + "1001";
        使用的Statement对象执行sql, 效率比PreparedStatement低。


       $:可以替换表名或者列名, 你能确定数据是安全的。可以使用$ 

      

             

       

    # 和 $区别
      1. #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
      2. #能够避免sql注入,更安全。
      3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
      4. $有sql注入的风险,缺乏安全性。
      5. $:可以替换表名或者列名


    3. mybatis的输出结果
    mybatis执行了sql语句,得到java对象。

      1)resultType结果类型, 指sql语句执行完毕后, 数据转为的java对象, java类型是任意的。
        resultType结果类型的它值

           1. 类型的全限定名称

           2. 类型的别名, 例如 java.lang.Integer别名是int

    处理方式:
      1. mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象。
      2. mybatis把ResultSet指定列值付给同名的属性。


      <select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
        select id,name, email,age from student
      </select>

      对等的jdbc
        ResultSet rs = executeQuery(" select id,name, email,age from student" )
        while(rs.next()){
          Student student = new Student();
          student.setId(rs.getInt("id"));
          student.setName(rs.getString("name"))
        }

      2) 定义自定义类型的别名
        1)在mybatis主配置文件中定义,使<typeAlias>定义别名
        2)可以在resultType中使用自定义别名


      3)resultMap:结果映射, 指定列名和java对象的属性对应关系。
        1)你自定义列值赋值给哪个属性
        2)当你的列名和属性名不一样时,一定使用resultMap


      resultMap和resultType不要一起用,二选一

           代码部分

     1     //Dao
     2     //返回一个值
     3     int countStudent();
     4     //返回map
     5     Map<Object,Object> selectMapById(Integer id);
     6     //使用resultMap定义映射关系
     7     List<Student> selectAllStudents();
     8     //列名和属性名不一致时,第一种方法
     9     List<MyStudent> selectAllMyStudents();
    10     //列名和属性名不一致,第二种方法
    11     List<MyStudent> selectDiffColProperty();
    12     //第一种模糊查询,在java代码中指定 like的内容
    13     List<Student> selectLikeOne(String name);
    14     //第二种方式,name就是李值,在mapper中拼接 like "%"李"%"
    15     List<Student> selectLikeTwo(String name);
     1   <!--sql执行后返回一行一列-->  <!--resultType="int" 全限定名称,也可以是 resultType="java.lang.Integer"-->
     2     <select id="countStudent" resultType="int">
     3         select count(*) from student
     4     </select>
    5 <!--返回Map 6 1)列名是map的key,列值是map的value 7 2)只能最多返回一行记录,否则会报错 8 --> 9 <select id="selectMapById" resultType="java.util.HashMap"> 10 select id,name,age from student where id=#{stuid} 11 </select>
    12 <!--使用resultMap 13 1)先定义resultMap 14 2)在select标签,使用resultMap来引用1的定义 15 --> 16 <!--定义resultMap 17 id:自定义名称 18 type:java类型全限定名称 19 --> 20 <resultMap id="studentMap" type="com.rzpt.domain.Student"> 21 <!--列名和属性的关系--> 22 <!--主键列,使用id标签--> 23 <id column="id" property="id"/> 24 <!--非主键列--> 25 <result column="name" property="name"/> 26 <result column="email" property="email"/> 27 <result column="age" property="age"/> 28 </resultMap> 29 <select id="selectAllStudents" resultMap="studentMap"> 30 select id,name,email,age from student 31 </select> 32 33 <!--列名和属性名不一致时--> 34 <resultMap id="MyStudentMap" type="com.rzpt.domain.MyStudent"> 35 <!--列名和属性的关系--> 36 <!--主键列,使用id标签--> 37 <id column="id" property="stuId"/> 38 <!--非主键列--> 39 <result column="name" property="stuName"/> 40 <result column="email" property="stuEmail"/> 41 <result column="age" property="stuAge"/> 42 </resultMap> 43 <select id="selectAllMyStudents" resultMap="MyStudentMap"> 44 select id,name,email,age from student 45 </select> 46 <!--列名和属性名不一致,第二种方法 47 resultType原则是同名的列值赋值给同名的属性值 48 所有使用列别名(java对象的属性名) 49 --> 50 <select id="selectDiffColProperty" resultType="com.rzpt.domain.MyStudent"> 51 select id as stuId,name as stuName,email as stuEmail,age as stuAge from student 52 </select>
    53 <!-- 第一种 like java代码中指定 like内容--> //
    String name="%刘%";
    54    <select id="selectLikeOne" resultType="com.rzpt.domain.Student">
    55     select id,name,email,age from student where name like#{name}
    56   </select>
    57 <!-- 第二种 like,name就是李值,在mapper中拼接 like "%" 李" %"--> 58 <select id="selectLikeTwo" resultType="com.rzpt.domain.Student"> 59 select id,name,email,age from student where name like "%" #{name} "%" 60 </select>

    第四章 动态sql
    动态sql: sql的内容是变化的,可以根据条件获取到不同的sql语句。
    主要是where部分发生变化。

    动态sql的实现,使用的是mybatis提供的标签, <if> ,<where>,<foreach>

      1)<if>是判断条件的,
        语法<if test="判断java对象的属性值">
            部分sql语句
          </if>

      2)<where> 用来包含 多个<if>的, 当多个if有一个成立的, <where>会自动增加一个where关键字,
        并去掉 if中多余的 and ,or等。

      3)<foreach> 循环java中的数组,list集合的。 主要用在sql的in语句中。
        学生id是 1001,1002,1003的三个学生

        select * from student where id in (1001,1002,1003)

       


      4)sql代码片段, 就是复用一些语法
        步骤
        1.先定义 <sql id="自定义名称唯一"> sql语句, 表名,字段等 </sql>
        2.再使用, <include refid="id的值" />

      代码部分 

     1     //Dao
     2     //动态sql,使用java对象作为参数 and
     3     List<Student> selectStudentIf(Student student);
     4     //动态sql,or
     5     List<Student>selectStudentIfOr(Student student);
     6 
     7     //where
     8     List<Student>selectStudentWhere(Student student);
     9     //foreach 用法1 集合放简单类类型
    10     List<Student> selectForeachOne(List<Integer> idlist);
    11     //foreach,用法2,集合放对象
    12     List<Student> selectForeachTwo(List<Student> stulist);
    13     //使用PageHelper分页数据
    14     List<Student> selectAll();
     1 <mapper namespace="com.rzpt.dao.StudentDao">
     2     <!--自定义sql片段-->
     3     <sql id="studentSql">
     4         select id,name,email,age from student
     5 
     6     </sql>
     7 
     8     <!--if
     9         <if.test+"使用参数java对象的属性值作为判断条件,语法为:属性=xxx值"
    10     -->
    11     <select id="selectStudentIf" resultType="com.rzpt.domain.Student">
    12         /*select id,name,age,email from student*/
    13         <include refid="studentSql"/>
    14         where
    15         <if test="name != null and name !=''">
    16             name=#{name}
    17         </if>
    18         <if test="age>0">
    19             and age>#{age}
    20         </if>
    21     </select>
    22     <!--1=1 的作用是防止一端出现不满足的情况下sql语句错误 where会弥补这个问题-->
    23     <select id="selectStudentIfOr" resultType="com.rzpt.domain.Student">
    24         select id,name,age,email from student
    25         where id>0
    26         <if test="name != null and name !=''">
    27             name=#{name}
    28         </if>
    29         <if test="age>20">
    30             or age>#{age}
    31         </if>
    32     </select>
    33 
    34     <!--where 会自动删除多余的语句-->
    35     <select id="selectStudentWhere" resultType="com.rzpt.domain.Student">
    36         select id,name,age,email from student
    37         <where>
    38             <if test="name != null and name !=''">
    39                 name=#{name}
    40             </if>
    41             <if test="age>20">
    42                 or age>#{age}
    43             </if>
    44         </where>
    45 
    46     </select>
    47 <!--foreach使用,List放简单数据类型<Integer>--> 48 <select id="selectForeachOne" resultType="com.rzpt.domain.Student"> 49 select * from Student where id in 50 <!-- 51 collection:表示接口中的方法参数的类型,如果是数组使用array,如何是list使用list 52 item:自定义的表示数组和集合成员的变量 53 open:循环开始的字符 54 close:循环结束的字符 55 separator:集合成员之间的分割符 56 --> 57 <foreach collection="list" item="myid" open="(" close=")" separator=","> 58 #{myid} 59 </foreach> 60 </select>
    61 <!--foreach使用,List放对象--> 62 <select id="selectForeachTwo" resultType="com.rzpt.domain.Student"> 63 select * from Student where id in 64 <foreach collection="list" item="stu" open="(" close=")" separator=","> 65 #{stu.id} 66 </foreach> 67 </select> 68 <!--selectAll 分页,查询所有--> 69 <select id="selectAll" resultType="com.rzpt.domain.Student"> 70 select * from student order by id 71 </select> 72 </mapper>

    测试代码:

      1 //动态sql
      2     @Test
      3     public void testSelectStudentIf() {
      4         SqlSession sqlSession = MyBatisUtils.getSqlSession();
      5         StudentDao dao = sqlSession.getMapper(StudentDao.class);
      6         Student student=new Student();
      7         student.setName("刘备");
      8         student.setAge(20);
      9         List<Student> students = dao.selectStudentIf(student);
     10         for (Student stu:students){
     11             System.out.println("if...and"+stu);
     12         }
     13     }
     14     //or
     15     @Test
     16     public void testSelectStudentIfOr() {
     17         SqlSession sqlSession = MyBatisUtils.getSqlSession();
     18         StudentDao dao = sqlSession.getMapper(StudentDao.class);
     19         Student student=new Student();
     20         //name为条件不满足会提示sql语句错误,需要在sql语句加一个恒成立的式子
     21         student.setName("");
     22         student.setAge(34);
     23         List<Student> students = dao.selectStudentIfOr(student);
     24         for (Student stu:students){
     25             System.out.println("if...or"+stu);
     26         }
     27     }
     28     //where
     29     @Test
     30     public void testSelectStudentWhere() {
     31         SqlSession sqlSession = MyBatisUtils.getSqlSession();
     32         StudentDao dao = sqlSession.getMapper(StudentDao.class);
     33         Student student=new Student();
     34         //name为条件不满足会提示sql语句错误,需要在sql语句加一个恒成立的式子
     35         //student.setName("张三");
     36         student.setAge(34);
     37         List<Student> students = dao.selectStudentWhere(student);
     38         for (Student stu:students){
     39             System.out.println("where"+stu);
     40         }
     41     }
     42     //以前的拼接,现在有foreach完成
     43     @Test
     44     public void testfor(){
     45         List<Integer> list=new ArrayList<>();
     46         list.add(1001);
     47         list.add(1002);
     48         list.add(1003);
     49         String sql ="select * from student where id in";
     50         StringBuilder sb=new StringBuilder();
     51         sb.append("(");
     52         for (Integer i:list){
     53             sb.append(i).append(",");
     54         }
     55         //删除末尾
     56         sb.deleteCharAt(sb.length()-1);
     57         sb.append(")");
     58         sql=sql+sb.toString();
     59         System.out.println("拼接的sql"+sql);
     60     }
     61     //foreach 集合里面是基本数据类型
     62     @Test
     63     public void testSelectForeachOne() {
     64         SqlSession sqlSession = MyBatisUtils.getSqlSession();
     65         StudentDao dao = sqlSession.getMapper(StudentDao.class);
     66         List<Integer> list=new ArrayList<>();
     67         list.add(1);
     68         list.add(2);
     69         list.add(3);
     70         List<Student> students = dao.selectForeachOne(list);
     71         for (Student stu:students){
     72             System.out.println("foreach"+stu);
     73         }
     74     }
     75     //foreach  集合里面是对象
     76     @Test
     77     public void testSelectForeachTwo() {
     78         SqlSession sqlSession = MyBatisUtils.getSqlSession();
     79         StudentDao dao = sqlSession.getMapper(StudentDao.class);
     80         List<Student> stuList=new ArrayList<>();
     81         Student s1=new Student();
     82         s1.setId(4);
     83         stuList.add(s1);
     84         s1=new Student();
     85         s1.setId(5);
     86         stuList.add(s1);
     87         List<Student> students = dao.selectForeachTwo(stuList);
     88         for (Student stu:students){
     89             System.out.println("foreach"+stu);
     90         }
     91     }
     92     //分页
     93     @Test
     94     public void testSelectAll() {
     95         SqlSession sqlSession = MyBatisUtils.getSqlSession();
     96         StudentDao dao = sqlSession.getMapper(StudentDao.class);
     97         //加入PageHelper的方法,分页
     98         //pageNum:第几页
     99         //pageSize:一页有多少数据
    100         PageHelper.startPage(3,3);
    101         List<Student> students = dao.selectAll();
    102         for (Student stu:students){
    103             System.out.println("分页"+stu);
    104         }
    105     }
    测试代码

    第五章:配置文件
    1. 数据库的属性配置文件: 把数据库连接信息放到一个单独的文件中。 和mybatis主配置文件分开。
    目的是便于修改,保存,处理多个数据库的信息。

      1)在resources目录中定义一个属性配置文件, xxxx.properties ,例如 jdbc.properties
        在属性配置文件中, 定义数据,格式是 key=value
        key: 一般使用 . 做多级目录的。
        例如 jdbc.mysql.driver , jdbc.driver, mydriver
           jdbc.driver=com.mysql.jdbc.Driver
           jdbc.url=jdbc:mysql//.....
           jdbc.username=root
           jdbc.password=123456

                            

           

      2)在mybatis的主配置文件,使用<property> 指定文件的位置
        在需要使用值的地方, ${key}

    2.mapper文件,使用package指定路径
      

     1 <mappers>
     2         <!--第一种方式,指定多个mapper文件位置-->
     3         <mapper resource="com/rzpt/dao/StudentDao.xml"/>
     4         <!--第二种方式,使用包名
     5             name:xml文件所在的包名,这个包名所有的xml文件一次一次都能加载给mybatis
     6                 1.mapper文件名称需要和接口名称一样,区分大小写
     7                 2.mapper文件和dao接口在同一目录
     8         -->
     9        <!-- <package name="com.rzpt.dao"/>-->
    10     </mappers>
    View Code

    第六章:PageHelper

      PageHelper做数据分页的。

     1 //分页
     2     @Test
     3     public void testSelectAll() {
     4         SqlSession sqlSession = MyBatisUtils.getSqlSession();
     5         StudentDao dao = sqlSession.getMapper(StudentDao.class);
     6         //加入PageHelper的方法,分页
     7         //pageNum:第几页
     8         //pageSize:一页有多少数据
     9         PageHelper.startPage(3,3);
    10         List<Student> students = dao.selectAll();
    11         for (Student stu:students){
    12             System.out.println("分页"+stu);
    13         }
    14     }
  • 相关阅读:
    mybatis-config.xml详解
    过滤器与拦截器
    Tomcat 部署web 项目
    Tomcat架构
    git stash
    AbstractQueuedSynchronizer 源码解读(转载)
    Kafka 转载
    Oracle数据库TNS详解
    Oracle建表知识全面详解
    Oracle高级教程
  • 原文地址:https://www.cnblogs.com/yumu77/p/13956506.html
Copyright © 2011-2022 走看看