• 【Java EE 学习 79 上】【mybatis 基本使用方法】


    一、简介

      mybatis类似于hibernate,都是简化对数据库操作的框架,但是和hibernate不同的是,mybatis更加灵活,整体来说框架更小,这体现在它需要我们手写SQL语句,而hibernate则将对数据库的操作对程序员完全透明了,程序员只需要按照面向对象的思想编写代码即可,想要看sql语句,就必须在配置文件中声明

    <property name="show_sql">true</property>

      hibernate对数据库的操作封装的非常彻底,因此灵活性不高,mybatis能够实现类似于hibernate的功能,但是需要自己写sql语句,这并不表示使用mybatis更加繁琐,相反的,个人认为mybatis框架很小,配置起来也非常简单,mybatis真正优秀的地方在哪里,为什么它会越来越火?

      mybatis官方给出的mybatics 3.1.1文档中有这么一段话说出了为何mybatis这么火的原因:

      

      其中文意思大概就是:Mybatis提供的完整功能集能够通过使用基于“映射语言”的XML来实现,这正是Mybatis流行这么多年的原因。

      以上内容是mybatis中的“映射文件”相关的内容,从这段话中不难看出。Mybatis的核心是“映射文件”,通过该映射文件能够实现Mybatis的所有功能。其形式如上所示。

    二、Mybatis的基本使用方法

       练习项目源代码:https://github.com/kdyzm/day79_1_mybatisdemo

      1.总的配置文件

        和hibernate有些相似,Mybatis中也有两种配置文件,一种配置文件是“总的配置文件”,类似于hibernate中的hibernate.cfg.xml,名字随意,但是最好起一个比较规范的名字,能够见名知意,我习惯使用mybatis-config.xml命名。在mybatis 3.1.1文档中有详细的使用说明,其提供了最简单的使用形式:

     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE configuration
     3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
     4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
     5 <configuration>
     6     <environments default="development">
     7         <environment id="development">
     8             <transactionManager type="JDBC" />
     9             <dataSource type="POOLED">
    10                 <property name="driver" value="${driver}" />
    11                 <property name="url" value="${url}" />
    12                 <property name="username" value="${username}" />
    13                 <property name="password" value="${password}" />
    14             </dataSource>
    15         </environment>
    16     </environments>
    17     <mappers>
    18         <mapper resource="org/mybatis/example/BlogMapper.xml" />
    19     </mappers>
    20 </configuration>

      配置文件的位置任意,但是推荐放到classpath路径下,文档中说明该文件可以放到任意位置,在windows下可以使用file:///协议直接访问,但是我没试过。

      以上内容非常简单,将对应的变量替换掉,接下来就是配置所谓的“映射文件”BlogMapper.xml。

      2.映射文件

      映射文件的写法和形式如下:

    1 <?xml version="1.0" encoding="UTF-8" ?>
    2 <!DOCTYPE mapper
    3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5 <mapper namespace="org.mybatis.example.BlogMapper">
    6     <select id="selectBlog" parameterType="int" resultType="Blog">
    7         select * from Blog where id = #{id}
    8     </select>
    9 </mapper>

      同样这也是文档中给出的例子,当然,这是最简单的例子,但是所有的配置文件中都需要对其进行配置,可以说是最核心而且是最基础的配置方式了。

      说明:

        namespace属性:命名空间,该命名空间的值任意,但是必须保证在整个项目中唯一,对应一个实体如Student,一定要有一个唯一的命名空间,所以这里直接取该实体的类名即可。

        mapper标签中的内容是所有对数据库操作的sql语句。这里的select标签表示里面的呃sql语句是查询语句,如果是update标签,表示是更新语句......

        id属性:该属性表示唯一,这自然不必说,但是该属性只是在当前Mapper标签中唯一即可。在引用该sql语句的时候,直接使用namespace+.+id来表示。

        parameterType:参数类型,这里表示的是#{id}中的id对应的参数类型。

        resultType:结果集类型,如果是Student,则不应当直接写上Student,而应当写上com.kdyzm.domain.Student,这里能够直接写上Blog是因为该Blog是已经声明了的“引用类型”。引用的写法之后再说。

    三、使用Mybatis的CRUD操作。

      和hibernat相同,mybatis的CRUD操作都依赖于一个Session对象,但是该对象在mybatis中有了新名字,名为SqlSession,而且创建它使用的工厂名字也不再是SessionFactory,而是SqlSessionFactory,示例代码如下:

      获取SqlSessionFactory对象的方式:

    String resource = "org/mybatis/example/mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

      获取SqlSession对象的方式:

    SqlSession session = sqlSessionFactory.openSession();

      之后就是使用Session对象的使用问题了。

      1.准备工作

      下载相关jar包并加入classpath,过程略,下载地址:https://github.com/mybatis/mybatis-3/releases

      (1)log4j配置文件

      为了方便查看控制台输出使用的log4j的配置文件:

     1 log4j.rootLogger=DEBUG, Console
     2 #Console
     3 log4j.appender.Console=org.apache.log4j.ConsoleAppender
     4 log4j.appender.Console.layout=org.apache.log4j.PatternLayout
     5 log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
     6 log4j.logger.java.sql.ResultSet=INFO
     7 log4j.logger.org.apache=INFO
     8 log4j.logger.java.sql.Connection=DEBUG
     9 log4j.logger.java.sql.Statement=DEBUG
    10 log4j.logger.java.sql.PreparedStatement=DEBUG
    log4j.properties

      (2)总的配置文件

     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE configuration
     3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
     4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
     5 <configuration>
     6     <environments default="development">
     7         <environment id="development">
     8             <transactionManager type="JDBC" />
     9             <dataSource type="POOLED">
    10                 <property name="driver" value="com.mysql.jdbc.Driver" />
    11                 <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
    12                 <property name="username" value="root" />
    13                 <property name="password" value="5a6f38" />
    14             </dataSource>
    15         </environment>
    16     </environments>
    17     <mappers>
    18         <mapper resource="com/kdyzm/domain/Student.xml"/>
    19         <mapper resource="com/kdyzm/domain/Person.xml"/>
    20         <mapper resource="com/kdyzm/domain/Clazz.xml"/>
    21     </mappers>
    22 </configuration>
    mybatis-config.xml

      总的配置文件中并没有什么实质性的东西,最核心的配置都在“映射文件”中。

      (3)新建3个类:

     1 package com.kdyzm.domain;
     2 
     3 public class Student {
     4     private Integer id;
     5     private String name;
     6     private String password;
     7     private Integer age;
     8     private Clazz clazz;
     9     /*************************** 分割线 ******************************************/
    10     public Integer getId() {
    11         return id;
    12     }
    13 
    14     public void setId(Integer id) {
    15         this.id = id;
    16     }
    17 
    18     public String getName() {
    19         return name;
    20     }
    21 
    22     public void setName(String name) {
    23         this.name = name;
    24     }
    25 
    26     public String getPassword() {
    27         return password;
    28     }
    29 
    30     public void setPassword(String password) {
    31         this.password = password;
    32     }
    33 
    34     public Integer getAge() {
    35         return age;
    36     }
    37 
    38     public void setAge(Integer age) {
    39         this.age = age;
    40     }
    41     
    42     public Clazz getClazz() {
    43         return clazz;
    44     }
    45     
    46     public void setClazz(Clazz clazz) {
    47         this.clazz = clazz;
    48     }
    49     
    50     @Override
    51     public String toString() {
    52         return "Student [id=" + id + ", name=" + name + ", password=" + password + ", age=" + age + "]";
    53     }
    54 }
    com.kdyzm.domain.Student
     1 package com.kdyzm.domain;
     2 
     3 public class Person {
     4     private int personId;
     5     private String personName;
     6     private String personAge;
     7 /****************************华丽的分割线***************************************/
     8     public int getPersonId() {
     9         return personId;
    10     }
    11     public void setPersonId(int personId) {
    12         this.personId = personId;
    13     }
    14     public String getPersonAge() {
    15         return personAge;
    16     }
    17     public void setPersonAge(String personAge) {
    18         this.personAge = personAge;
    19     }
    20     public String getPersonName() {
    21         return personName;
    22     }
    23     public void setPersonName(String personName) {
    24         this.personName = personName;
    25     }
    26     @Override
    27     public String toString() {
    28         return "Person [personId=" + personId + ", personName=" + personName + ", personAge=" + personAge + "]";
    29     }
    30 }
    com.kdyzm.domain.Person
     1 package com.kdyzm.domain;
     2 
     3 import java.util.List;
     4 
     5 public class Clazz {
     6     private int id;
     7     private String name;
     8     private String desc;
     9     private List<Student> students;
    10 /*************************华丽的分割线************************/
    11     public int getId() {
    12         return id;
    13     }
    14     public void setId(int id) {
    15         this.id = id;
    16     }
    17     public String getName() {
    18         return name;
    19     }
    20     public void setName(String name) {
    21         this.name = name;
    22     }
    23     public String getDesc() {
    24         return desc;
    25     }
    26     public void setDesc(String desc) {
    27         this.desc = desc;
    28     }
    29     public List<Student> getStudents() {
    30         return students;
    31     }
    32     public void setStudents(List<Student> students) {
    33         this.students = students;
    34     }
    35     @Override
    36     public String toString() {
    37         return "Clazz [id=" + id + ", name=" + name + ", desc=" + desc + "]";
    38     }    
    39 }
    com.kdyzm.domain.Clazz

      用的最多的两个类是Student和Clazz,Person类基本上没用上。

      2.查询

        com.kdyzm.domain.Student.xml配置文件中的mapper标签:

    <mapper namespace="com.kdyzm.domain.Student"></mapper>

      (1)查询一个Student对象

    <select id="selectUserById" parameterType="int" resultMap="com.kdyzm.domain.Student">
         select s.* ,c.* from student s,clazz c where s.clazz=c.clazzid and s.studentid=#{id};
    </select>

        java代码:

    Student student=session.selectOne("com.kdyzm.domain.Student.selectUserById", "1");

      (2)查询Student的集合

    <select id="selectAllStudent" resultType="com.kdyzm.domain.Student">
        select * from Student
    </select>

      java代码:

    Collection<Student> students=sqlSession.selectList("com.kdyzm.domain.Student.selectAllStudent");

      3.插入

    <insert id="insertIntoStudent" parameterType="com.kdyzm.domain.Student">
            insert into
            student(studentid,name,password,age) values(#{id},#{name},#{password},#{age})
        </insert>

      java代码:

    1 String statement="com.kdyzm.domain.Student.insertIntoStudent";
    2 Student student=new Student();
    3 student.setId(7);
    4 student.setName("张三");
    5 student.setAge(13);
    6 student.setPassword("xiaozhang");
    7 int result=session.insert(statement, student);
    8 session.commit();

      这里一定不要忘了提交的动作:commit();

      4.更新

    <update id="updateStudentByStudentObject" parameterType="com.kdyzm.domain.Student">
        update
        student set name=#{name},password=#{password},age=#{age} where
        studentid=#{id}
    </update>

      5.删除

    <delete id="deleteUserById" parameterType="string">
        delete from student
        where studentid = #{id}
    </delete>

    四、注意事项

      1.parameterType属性和resultType属性的类型问题

        (1)经常使用parameterType类型为string或者int类型作为id对一个对象进行操作,经常传入一个对象的类型如com.kdyzm.domain.Student对一个对象进行修改操作,可以使用HashMap类型来替换对象类型,这时候类型值就需要写上hashMap。  

        (2)返回值是一个对象还是一个对象的集合,返回值类型都是同一种,如果是普通对象类型,那么以Student为例就是com.kdyzm.domain.Student,如果是HashMap类型,那么就是hashMap。

      2.parameterType的类型问题

        如果parameterType类型是基本数据类型或者String类型,那么在sql中的#{id}中的id名字可以任意写,只是起着占位符的作用,但是如果是对象类型的话,则名字就需要和对象中的属性名完全相同才行,因为需要调用对象的get方法获取字段的值。

    五、解决数据库中表的字段和对象中的属性字段名字不一致的情况

      解决方法有两种:

      1.第一种方式是大家首先能够想到的最通用的方式,那就是起别名,如

    select id as studentId,name as studentName from student

      但是使用这种方式有一个非常明显的缺点,那就是针对每一次查询都必须这么写,显得非常乱而且书写起来非常的不方便,还容易出错,导致的直接后果就是效率低下。

      使用第二种方式能够解决这种麻烦。

      2.第二种解决方式和在hibernate中的配置方式很相似,都是映射表中的字段到对象中的属性字段的方法。

    <!-- 使用ResultMap标签解决数据库中表的字段和类中的属性字段不一致的情况 -->
    <resultMap type="com.kdyzm.domain.Person" id="personMap">
        <id column="id" property="personId"/>
        <result column="name" property="personName"/>
        <result column="age" property="personAge"/>
    </resultMap>

      其中column中填写数据库表中的列名,property中填写对应对象中的字段名。

    六、多对一关系查询和一对多关系查询

      在hibernate中我们经常使用关联关系查询,比如查到了Student对象之后直接就能够获取Clazz对象,获取了Clazz对象之后直接就能够得到List<Student>对象,同样,在mybatis中也能欧做到这一点,这里先不考虑懒加载的事情。

      这里使用Student和Clazz为例说明

      1.一对多关系

         Clazz和Student之间是一对多的关系,现在的需求就是根据Clazz对象获取所有的Student对象。

        可以利用之前提到的resultMap标签实现这一点,首先需要在Clazz类中有List<Student>students成员变量,同时提供对应的set/get方法;然后进行映射文件中的XML文件的配置:

     1 <resultMap type="com.kdyzm.domain.Clazz" id="clazzMap">
     2     <id property="id" column="clazzid"></id>
     3     <result property="name" column="name" />
     4     <result column="describtion" property="desc" />
     5     <collection property="students" ofType="com.kdyzm.domain.Student">
     6         <id column="studentid" property="id"></id>
     7         <result column="name" property="name" />
     8         <result column="password" property="password" />
     9         <result column="age" property="age" />
    10     </collection>
    11 </resultMap>

        和之前不太相同的是添加了黄色背景部分的内容。

        property属性对应着类中的字段名称,ofType属性是集合中的元素类型。collection标签的子标签是ofType类型中的所有成员变量,当然虽然Student类中有Clazz类型的成员变量,但是这里不要写上,除此之外所有的成员变量都要写上。

      sql查询的方式也要修改,这里必须是两表联合查询才行,同时将resultType改成resultMap:

    1 <select id="selectClazzById" resultMap="clazzMap" parameterType="int">
    2     select s.*,c.* from student s,clazz c where c.clazzid =#{id} and s.clazz=c.clazzid
    3 </select>

      java代码:

    1 String statement = "com.kdyzm.domain.Clazz.selectClazzById";
    2 Clazz clazz = session.selectOne(statement, "1");
    3 List<Student> students = clazz.getStudents();
    4 for (Student student : students) {
    5     System.out.println(student);
    6 }

      2.多对一关系的实现

      Student对象和Clazz对象之间是多对一的关系,现在的需求就是需要根据Student对象获取其对应的Clazz对象。

      这里还是需要借助于resultMap标签:

     1 <resultMap type="com.kdyzm.domain.Student" id="studentMap">
     2     <id column="studentid" property="id"></id>
     3     <result column="name" property="name"/>
     4     <result column="password" property="password"/>
     5     <result column="age" property="age"/>
     6     <association property="clazz" javaType="com.kdyzm.domain.Clazz">
     7         <id property="id" column="clazzid"></id>
     8         <result property="name" column="name"/>
     9         <result column="describtion" property="desc" />
    10     </association>
    11 </resultMap>

      当然了,最关键的还是以上黄色背景部分的内容,这里使用association标签完成任务。

      property属性填写的是对象中的相应字段,javaType对应的是其java类型。然后association标签内填写该对象中的所有属性和表中字段的对应关系,注意,所有的一定都要填写完整,否则没有填写完整的部分对应的字段就会是NULL类型。

      当然,查询的sql语句也必须改变,改成两张表的联合查询:

    <!-- 根据UserId查询User对象的查询方法 -->
    <select id="selectUserById" parameterType="int" resultMap="studentMap">
         select s.* ,c.* from student s,clazz c where s.clazz=c.clazzid and s.studentid=#{id};
    </select>

      java代码如下:

    String statement = "com.kdyzm.domain.Student.selectUserById";
    Student student = session.selectOne(statement, "1");
    System.out.println(student.getClazz());

    七、mybatics的基础部分内容就是这么多,接下来是和spring的整合过程。

  • 相关阅读:
    七、正规式到正规文法与自动机
    正规文法与正规式
    Class文件加载详解
    ReentrantLock和Synchronized的区别
    synchronized的原理及锁升级
    (四)项目接入springcloud alibaba
    (三)项目搭建
    使用npm install安装前端项目依赖时报错
    java并发编程(二)
    (二)搭建虚拟机环境
  • 原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/5079937.html
Copyright © 2020-2023  润新知