MyBatis入门与项目实践

为什么要使用MyBatis?

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

JDBC数据库编程

传统的JDBC数据库编程目前在项目实战中已经几乎绝迹了,原因等我们看一个例子之后稍作分析。这是一个简单的JDBC数据库连接代码例子:

    public Student findStudentById(int studId)  
    {  
        Student student = null;  
        Connection conn = null;  
        try  
        {  
            //获得数据库连接  
            conn = getDatabaseConnection();  
            String sql = "SELECT * FROM STUDENTS WHERE STUD_ID=?";  
            //创建  PreparedStatement  
            PreparedStatement pstmt = conn.prepareStatement(sql);  
            //设置输入参数  
            pstmt.setInt(1, studId);  
            ResultSet rs = pstmt.executeQuery();  
            //从数据库中取出结果并生成 Java 对象  
            if(rs.next())  
            {  
                student = new Student();  
                student.setStudId(rs.getInt("stud_id"));  
                student.setName(rs.getString("name"));  
                student.setEmail(rs.getString("email"));  
                student.setDob(rs.getDate("dob"));  
            }  
        }  
        catch (SQLException e)  
        {  
            throw new RuntimeException(e);  
        }  
        finally  
        {  
            //关闭连接  
            if(conn != null)  
            {  
                try  
                {  
                    conn.close();  
                }  
                catch (SQLException e) { }  
            }  
        }  
        return student;  
    }  
      
    public void createStudent(Student student)  
    {  
        Connection conn = null;  
        try  
        {  
            //获得数据库连接  
            conn = getDatabaseConnection();  
            String sql = "INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB)  
                         VALUES(?,?,?,?)";  
            //创建 PreparedStatement  
            PreparedStatement pstmt = conn.prepareStatement(sql);  
            //设置输入参数  
            pstmt.setInt(1, student.getStudId());  
            pstmt.setString(2, student.getName());  
            pstmt.setString(3, student.getEmail());  
            pstmt.setDate(4, new  
                          java.sql.Date(student.getDob().getTime()));  
            pstmt.executeUpdate();  
        }  
        catch (SQLException e)  
        {  
            throw new RuntimeException(e);  
        }  
        finally  
        {  
            //关闭连接  
            if(conn != null)  
            {  
                try  
                {  
                    conn.close();  
                }  
                catch (SQLException e) { }  
            }  
        }  
    }  
    protected Connection getDatabaseConnection() throws SQLException  
    {  
        try  
        {  
            Class.forName("com.mysql.jdbc.Driver");  
            return DriverManager.getConnection  
                   ("jdbc:mysql://localhost:3306/test", "root", "admin");  
        }  
        catch (SQLException e)  
        {  
            throw e;  
        }  
        catch (Exception e)  
        {  
            throw new RuntimeException(e);  
        }  
    }  

可以看出,JDBC编程需要如下几个步骤:

  1. JDBC连接数据库,注册驱动和数据库信息
  2. 操作Connection对象,打开Statement对象
  3. 通过Statement对象操作SQL语句
  4. 通过ResultSet对象读取数据,再转换为具体的POJO。
  5. 关闭数据库连接

可以看出JDBC数据库连接的工作量比较大,代码繁杂,有很多的模板代码。像异常的处理、数据库的关闭等都是模式化的处理流程。

Hibernate

Hibernate通过XML文件来与数据库进行交互,可以不需要编写SQL语句,直接使用HQL语句就可以了。
Hibernate屏蔽了SQL,所以只能全表映射,在字段较多的时候效率太低。

MyBatis

mybatis005.png

MyBatis是一个半自动映射的框架。它需要手动配置POJO、SQL和映射的关系。全表映射的Hibernate只需要配置POJO和映射的关系就可以了。
所以,MyBatis需要三个文件:POJO类,SQL语句,映射关系。
一个简单的MyBatis的例子:
a. 在 SQL Mapper 映射配置文件中配置SQL语句,假定为StudentMapper.xml

  

  
INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(#{studId},#{name},#{email},#{dob})
  

b. 创建一个StudentMapper接口.

public interface StudentMapper  
    {  
        Student findStudentById(Integer id);  
        void insertStudent(Student student);  
    }  

c. 在JAVA代码中使用MyBatis

SqlSession session = getSqlSessionFactory().openSession();  
StudentMapper mapper = session.getMapper(StudentMapper.class);  
// Select Student by Id  
Student student = mapper.selectStudentById(1);  
//To insert a Student record  
mapper.insertStudent(student);  

从这个小例子可以看出,MyBatis通过Mapper关联Mapper所关联的XML,在XML文件中定义动态的SQL语句。最后在JAVA程序中通过SqlSession来读写数据库。非常简单方便!

MyBatis配置

使用Maven配置MyBatis

新建一个Maven项目,在pom.xml文件中加入依赖。



    4.0.0

    cn.hwzheng
    mybatis
    1.0-SNAPSHOT
    
        org.springframework.boot
        spring-boot-starter-parent
        1.4.3.RELEASE
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.mybatis
            mybatis
            3.4.1
        
    

这里为了方便,我直接使用了SpringBoot来构建应用。SpringBoot已经自带了Tomcat服务器和Spring MVC等功能,提供一站式的解决方案。

MyBatis的基本构成

  • SqlSessionFactoryBulider:根据XML配置或者Java配置类来生成SqlSessionFactroy
  • SqlSessionFactroy:生成SqlSession的工厂类
  • SqlSession:是一个既可以发送SQL去执行并且返回结果又可以获取Mapper的接口。新的MyBatis推荐使用Mapper接口来操作数据库。
  • SQL Mapper:由JAVA接口和XML文件(或者注解类)组成,给出相应的SQL映射规则。Mapper负责发送SQL语句去执行,并且返回结果。

配置MyBatis的配置文件

配置MyBatis的配置文件
创建一个配置文件,这里我放在了com/cnc/config包下,文件名为mybatis-config.xml




    
        
            
            
                
                
                
                
            
        
    
    
        
    

替换掉数据库驱动、数据库URL、用户名、密码等,即可。

构建SqlSessionFactory

private String resource;
private InputStream inputStream;
private SqlSessionFactory sqlSessionFactory;

private void init() throws Exception{
    resource = "com/cnc/config/mybatis-config.xml";
    inputStream = Resources.getResourceAsStream(resource);
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}

sqlSessionFactory由mybatis-config.xml文件中的内容获取。有了sqlSessionFactory,就可以获取SqlSession了。

构建SqlSession
SqlSession的作用类似于公司的前台MM,你委托她做一件事,但是她可能是找她在我们公司的男朋友去办了,而我们并不知道是谁处理了这件事,只知道去找前台MM要结果。SQL语句其实是由内部的Executor接口来处理的。

SqlSession session = sqlSessionFactory.openSession();
try {
  Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
  session.close();
}

其中org.mybatis.example.BlogMapper.selectBlog是定义在BlogMapper里面的一个方法,使用注解标注。这多少有点让人迷惑,现在更加干净的方法是使用Mapper接口。

Mapper接口
使用Mapper接口来操作数据库是更加推荐的一种方法。在Mapper接口里定义各种SQL方法,用于操作数据库。Mapper接口读取Mapper.xml中的配置,绑定xml中已经定义好的SQL语句。

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(101);
} finally {
  session.close();
}

mapper.xml文件内容为:




  

ResultMap的用法
我们项目中经常遇到数据库的表中的字段名称与POJO的属性名称不同的情况,此时无法自动匹配,但是可以通过配置ResultMap的方式来配置。
比如User的字段名称为id、user_name,hashed_password,通过这个配置,就可以使用跟上面一样的方式来获取数据了。


  
  
  


只需要增加一个resultMap="userResultMap",然后经过userResultMap转换之后返回User对象。

操作实例——基于SpringBoot+MySQL数据库

MyBatis入门与项目实践_第1张图片
mybatis001.png

构建一个Maven项目,结构如图所示。用到的配置文件放到resources/config文件目录下,方便读取。似乎maven项目需要将所有的非JAVA代码放到resource文件夹下,才能正常读取。

pom.xml文件是Maven用于依赖管理的XML文件,这里我使用的是SringBoot+MyBatis3.4.1,所以需要添加这两项的依赖包。
登录:http://spring.io/,找到springboot依赖。

MyBatis入门与项目实践_第2张图片
mybatis003.png

pom.xml内容为:



    4.0.0

    cn.hwzheng
    mybatis
    1.0-SNAPSHOT
    
        org.springframework.boot
        spring-boot-starter-parent
        1.4.3.RELEASE
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.mybatis
            mybatis
            3.4.1
        
    

主要是加入MyBatis和SpringBoot的依赖。MyBatis的依赖数据放到dependencies标签下。

这里我使用的是MySQL数据库,MySQL数据库需要事先启动好。MyBatis的数据库配置信息如下:




    
        
            
            
                
                
                
                
            
        
    
    
        
    

事先在spring数据库里面配置一个名为USER的表。

MyBatis入门与项目实践_第3张图片
mybatis006.png

配置好了数据库之后,我设计了一个最简单的POJO,叫做User。有三个属性,id、LastName,firstName。对应于数据库中的ID、LASTNAME、FIRSTNAME三个字段。

package com.cnc.beans;

/**
 * Created by hwzheng on 2016/12/28.
 */
public class User {
    private int id;
    private String lastName;
    private String firstName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}

对应有一个Mapper接口,定义操作数据库的方法。其中SQL方法与Mapper的配置XML文件中的定义绑定。

package com.cnc.mapper;

import com.cnc.beans.User;

/**
 * Created by hwzheng on 2016/12/28.
 */
public interface UserMapper {
    User selectUser(int id);
    int insertUser(User user);
}

Mapper接口必须有一个配置XML文件,绑定Mapper接口中的方法。




    
    
        insert into USER (ID, FIRSTNAME, LASTNAME) values (#{id}, #{firstName}, #{lastName})
    

OK,万事俱备,开始使用!

package com.cnc.service;

/**
 * Created by hwzheng on 2016/12/28.
 */
import com.cnc.beans.User;
import com.cnc.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

import java.io.InputStream;

@Controller
@EnableAutoConfiguration
public class MainController {
    private String resource;
    private InputStream inputStream;
    private SqlSessionFactory sqlSessionFactory;

    private void init() throws Exception{
        resource = "config/mybatis-config.xml";
        inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @RequestMapping("/")
    @ResponseBody
    String home() {
        try {
            init();
        } catch (Exception e) {
            e.printStackTrace();
        }
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        User me = mapper.selectUser(1);
        User you = new User();
        you.setId(2);
        you.setFirstName("CHEN");
        you.setLastName("SHIJIE");
        mapper.insertUser(you);
        you = mapper.selectUser(2);
        User me = mapper.selectUser(2);
        sqlSession.commit();
        sqlSession.close();
        return "Hello " + me.getLastName() + " " + me.getFirstName() + "  " + you.getLastName() + " " + you.getFirstName();
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(MainController.class, args);
//        MainController controller = new MainController();
//        System.out.println(controller.home());
    }
}

如果需要最终将结果写入数据库,需要使用session.commit()将结果commit到数据库中。
运行,输入地址栏:http://localhost:8080/
看到结果:

MyBatis入门与项目实践_第4张图片
mybatis002.png

一个最简单的SpringMVC+MyBatis项目就此告成。

结语

本文使用到的仅仅是MyBatis的最基本的功能,MyBatis的许多配置和许多功能都没有涉及到,希望通过接下去的学习可以提高数据库方面的学习,在工作中更好地应用!

你可能感兴趣的:(MyBatis入门与项目实践)