当前位置:阳光沙滩 >Java > 查看文章

MyBatis不介绍,知道是一个持久化的框架即可!要熟悉Sql语句和Java

官方文档地址:

http://www.mybatis.org/mybatis-3/zh/index.html

直接上HelloWorld!

1.MyBatis Helloworld

首先,创建数据库吧,其实开发中也是,先设计一下表的字段。这里我们先创建一个数据表,就一个用户表:sob_user

1)我们创建数据库my_batis,然后用数据库软件连接一下!

Snip20180708_3

测试连接–>成功!

接下来我们就可以创建表了!我们这个用户表字段有:id,username,email,password

CREATE TABLE sob_user(`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
  `username` VARCHAR(255) NOT NULL ,
  `passowrd` VARCHAR(255) NOT NULL ,
  `email` VARCHAR(255) NOT NULL );

执行结果

sql> CREATE TABLE sob_user(`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
  `username` VARCHAR(255) NOT NULL ,
  `passowrd` VARCHAR(255) NOT NULL ,
  `email` VARCHAR(255) NOT NULL )
[2018-07-08 16:04:50] completed in 46ms

 

然后我们插入一条记录吧:

Snip20180708_5

测试一下查询

Snip20180708_6

好啦,数据库有了,表有了,记录有了!

接下来就开始MyBatis的Hello world吧!

下载相关的jar包,也可以用Maven来构建

这是MyBatis在github上的地址:

https://github.com/mybatis/mybatis-3

发布地址:

https://github.com/mybatis/mybatis-3/releases

我这里下载了一个 mybatis-3.4.6.zip的版本

接着我们引入jar包,添加依赖,我们还需要一个mysql的驱动

如下图:

Snip20180708_8

有了jar包,我们就要去看看文档怎么用了,在我们下载的zip文件里头有说明文档的:

Snip20180708_9

jar包我们有了,从文档里说,我们要配置一个xml文件,这个文件怎么配置的呢?在文档的下面就有说到了!

我们创建一个配置文件,放到conf目录下即可,这个配置文件名字我们叫:mybatis-config.xml

这是文档里的内容:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

大概的结构是这样子的:

Snip20180708_10

这个配置文件我们需要修改一下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  <!-- 名称空间 -->
<mapper namespace="org.mybatis.example.SobUserMapper">
<!-- id是唯一标识,后面的是返回类型,假设我们要返回我们的SobUser对象,那么就把这个bean类扔进去 -->
  <select id="selectSobUser" resultType="com.sunofbeaches.domain.SobUser">
  <!-- sql语句,后面这个是参数 也就是从传递过来的参数中拿到username,根据这个来chaxun-->
    select * from sob_user where username = #{username}
  </select>
</mapper>

 

 

有了这个配置文件了,前面我们看了文档,通过这个配置文件可以创建一个SqlSessionFactory

Building SqlSessionFactory from XML

怎么创建呢?文档里也有说:

我们也等下再说,我们还需要用到一个Mapper.xml,也就是一个映射配置文件

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  <!-- 名称空间 -->
<mapper namespace="org.mybatis.example.BlogMapper">
<!-- id是唯一标识,后面的是返回类型,假设我们要返回我们的SobUser对象,那么就把这个bean类扔进去 -->
  <select id="selectBlog" resultType="com.sunofbeaches.domain.SobUser">
  <!-- sql语句,后面这个是参数 也就是从传递过来的参数中拿到username,根据这个来chaxun-->
    select * from sob_user where username = #{username}
  </select>
</mapper>

接着还有一个bean类:

package com.sunofbeaches.domain;

public class SobUser {
	public int id;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	private String username;
	private String password;
	private String email;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "SobUser [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email + "]";
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
}

 

好啦,接下来真的是查询了,我们创建一个测试类的,用main作为入口,在web开发里的web.xml作为入口,这里我们先针对javase项目去使用mybatis。

package com.sunofbeaches.test;

import java.io.IOException;
import java.io.InputStream;

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 com.sunofbeaches.domain.SobUser;

public class MyBatisTest {

	public static void main(String[] args) throws IOException {
		//通过配置文件创建SqlSessionFactory
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		//sqlSessionFactory拿到SqlSession
		SqlSession openSession = sqlSessionFactory.openSession();
		
		//查询一个数据出来,第一个参数是唯一标识符,第二个是sql语句里的参数
		SobUser sobUser = openSession.selectOne("org.mybatis.example.SobUserMapper.selectSobUser", "BillGates");
		System.out.println(sobUser);
		
		openSession.close();
	}

}

 

 

还要配置一下Mapper的地址,也就是我们那个

Snip20180708_11

然后跑起来,就有了这样的结果:

Untitled6

2.MyBatis接口式编程

前面我们已经实现了一个Helloworld的小例子,但是有个弊端,就是我们查询的时候,传参数是个Ojbect类型,也就是传什么东西都可以,那么我们现在通过接口,定义好我们的参数和返回值。再由具体的类去实现查询即可,调用者不用管里面的实现逻辑。

 

首先我们定义接口:

Snip20180708_12

修改SobUserMapper文件

Snip20180708_13

package com.sunofbeaches.test;

import java.io.IOException;
import java.io.InputStream;

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 com.sunofbeaches.dao.ISobUserMapper;
import com.sunofbeaches.domain.SobUser;

public class MyBatisTest {

	public static void main(String[] args) throws IOException {
		//通过配置文件创建SqlSessionFactory
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		//sqlSessionFactory拿到SqlSession
		SqlSession openSession = sqlSessionFactory.openSession();
		
		//重点:
		//这次我们获取到Mapper,然后再去调用方法即可
		ISobUserMapper mapper = openSession.getMapper(ISobUserMapper.class);
		SobUser sobUserByName = mapper.getSobUserByName("BillGates");
		System.out.println(sobUserByName);
		//end
		
		openSession.close();
	}

}

 

运行,我们得到一样的结果,把内容查询出来了!

SobUser [id=1, username=BillGates, password=null, email=test@sunofbeaches.com]

3.MyBatis全局配置文件

关于配置,文档里面有详细的说明,主要是Mapper的配置和mybatis-config.xml的配置

Snip20180708_14

3.1.properties标签

	<properties resource="" url="">
		
	</properties>

 

properties里有两个参数,这两个参数用来指定资源路径的。

resource是指定class路径下的,而url用于指定网络路径或者磁盘上的路径。

我们比较常用的是用来引用数据库的配置,比如说前面我们是直接配置的,接下来我们把数据库的配置文件抽取出来,独立成一个dbconfig.properties文件

Snip20180708_15

怎么引用呢?

Snip20180708_16

这样子就可以使用了,以后呢就不需要修改这个配置文件了,如果数据库的配置变了,直接修改数据库的配置文件即可。

详情内容可以去看文档!

3.2.Settings

Snip20180708_17

关于设置项有很多,大家需要参考文档,看文档里头的说明,这里的话我们举个例子,比如说,我们java里的命令是userName,而数据库里可能是user_name,如果在没有配置的情况下,默认是匹配不上的。如果我们开启一个设置项:

mapUnderscoreToCamelCasEenables,这个设置项的描述是:Eenables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn.

把数据库中的字段,映射成JavaBean中的成员时,转在驼峰命名法,上面举了一个例子,在数据库中的字段是A_COLUMN,在javaBean中的成员则是aColumn,这样子就可以解决前面我们那个问题了。

默认值是false

我们怎么修改呢?

Snip20180708_18

3.3.typeAliases别名

我们在写sql语句就知道别名了,这里的别名是用来干嘛的呢?

A type alias is simply a shorter name for a Java type. It’s only relevant to the XML configuration and simply exists to reduce redundant typing of fully qualified classnames.

 比如说我们的Mapper:
Snip20180721_3
每次我们都写全类名,觉得累不累呢,如果方法多的时候,要写挺多的,对不对。
那么我们可以起个别名来简化一下。
怎么指定别名呢?在mybatis的配置文件下:
Snip20180721_4
使用:我们指定了别名以后就不需要写那么长的内容了,我们回到Mapper的配置文件里:
Snip20180721_5
这样子直接修改,是可以跑起来了,我们就不需要写全类名了!
但这么写,也要写很多代码,有没有更好的办法呢?有-批量起别名
Snip20180721_7
同样的,如这样起别名的话,默认就有一个类名的别名,别名不分大小写,你爱怎么写怎么写吧。
但是大家有没有发现什么问题?用package批量生成别名的话,假设名字冲突呢?比如说在这个包的下面还有一个子包,包里面有一个跟外面相同的类名,这个时候怎么办呢?
当然是手动指定别名啦!
我们可以通过注解的形式来解决这个问题,指定别名:
Snip20180721_8
有一些别名了,是已经预置好的,比如下:
Snip20180721_9
起别名的时候注意一下,不要跟预置的别名冲突。

3.4.environments

环境s

这玩意有什么用呢,翻译过来是环境的意思。

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
</environments>

以上是复制自文档的内容,从上面我们可以看到外层标签是environments,里面是单独的environment标签,换句话话,我们可以配置多个环境。

那么,这个配置是有什么用的呢?

在我们的实际开发中,我们有自己的开发环境,有测试环境,有上线的正式环境。我们配置好,在不同的时期使用不同的环境即可。

注意:environment标签里必须包含着dataSource和transactionManager否则会报错的呢!

Snip20180804_14

报错了吧!

不过还好,开发工具自动帮助我们填充内容,这就是开发工具的好处呀,坏处就是离开了开发工具,基本上有代码短板的现象。

environment的id呢表示当前这个环境配置的唯一标识

假设我们这里有两个环境,一个是开发环境,一个是测试环境,我们怎么样指定当前的环境呢?

很简单:

    <!--其实就是这个default用来指定当前使用哪个环境-->
    <environments default="test">
        <environment id="test">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${test.driver}"/>
                <property name="url" value="${test.url}"/>
                <property name="username" value="${test.user}"/>
                <property name="password" value="${test.password}"/>
            </dataSource>
        </environment>
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

这里面这个事物管理JDBC其实是一个别名,它是怎么对应的呢,我们可以看一下Configuration.

org.apache.ibatis.session.Configuration

Snip20180917_9

这里面的话注册了很多别名。

我们跟Spring整合的时候,我们就会把事物管理交给Spring了。单独使用的话直接复制官方文档的内容即可。

3.5.多数据库厂商的支持

databaseldProvider,这样就解决了mybatis在移植性上面的问题

<databaseIdProvider type="DB_VENDOR">
 <property name="SQL Server" value="sqlserver"/>
 <property name="DB2" value="db2"/>
 <property name="Oracle" value="oracle" />
</databaseIdProvider>

以上是文档里的例子,这是什么意思呢?

首先

  <databaseIdProvider type="DB_VENDOR">
        
    </databaseIdProvider>

这是一个固定写法

至于DB_VENDOR这个,其实也是个别名,可以看前面的说明去Configuration里找到对应的内容。

其实Vendor我们就知道这是个定制的,可扩展的了,如果有做过AOSP就知道了,一般厂商自己定义的东西就放在vendor目录下面。

那怎么使用呢?

第一步:

 <databaseIdProvider type="DB_VENDOR">
        <property name="MYSQL" value="mysql"/>
        <property name="ORACLE" value="oracle"/>
    </databaseIdProvider>

第二步:

在我们的语句中声明:

    <select id="getEmployeeByName" resultType="EmployeeBean" databaseId="mysql">
        SELECT * from tbl_employee WHERE last_name = #{lastName}
    </select>

    <select id="getEmployeeByName" resultType="EmployeeBean" databaseId="oracle">
        SELECT * from tbl_employee WHERE last_name = #{lastName}
    </select>

 

以上两条语句是一样的,假设我们的语句因为数据库平台不一样的时候,就会根据不同的id去执行了。

为什么会知道当前是什么数据库呢?因为api里是有接口获取的,而各个数据库平台的厂商要实现里面的方法,这样子就可以知道是什么数据库平台了,而对应地去执行sql语句。

3.6.Mapper

mapper是映射的意思,我们先说明一下mapper里面的属性

 

 

Snip20181208_51

url引用的是硬盘上的文件,或者网络文件

官方的例子:

<!-- Using url fully qualified paths -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>

resource的话,从我们的demo里就使用了,一般来说,我会创建一个文件夹用于存放,而文件夹的报名和映射的类名报名一样。而对应的mapper名字一样。

如下:

Snip20181208_52

class属性的话,注册类的全路径名称即可,但是有一个前提条件,就是mapper.xml和类要放在同一样的包名下,前面我们已经放到同一样的包明了,所以我们这么写:

Snip20181208_53

也是可以查询成功了。

还有一种写法就是用注解+类的形式,不写mapper.xml文件了

package com.sunofbeaches.dao;

import com.sunofbeaches.beans.EmployeeBean;
import org.apache.ibatis.annotations.Select;

/**
 * Created by TrillGates on 2018/12/8.
 */
public interface EmployeeManagerAnnotation {

    @Select("select * from tbl_employee where last_name = #{lastName}")
    EmployeeBean getEmployeeByName(String lastName);
}

注册:

Snip20181208_54

那什么时候用注解,什么时候用xml来配置呢?

简单的推荐使用注解,复杂的推荐使用配置文件。

每添加一个mapper就要写这一样个,这不是很麻烦吗?

其实可以全部一起注册,把某个包下面的mapper全部注册

Snip20181208_55

4.映射文件详解

对应的官方文档是:http://www.mybatis.org/mybatis-3/sqlmap-xml.html

Snip20181209_59

期中有一个过时了,我们就不去看了。

先看一下增删改吧,也就是insert delete update

首先,创建一个类:

package com.sunofbeaches.dao;

import com.sunofbeaches.beans.EmployeeBean;

/**
 * Created by TrillGates on 2018/12/9.
 */
public interface EmployeeAction {

    void insert(EmployeeBean employeeBean);

    void update(EmployeeBean employeeBean);

    void delete(EmployeeBean employeeBean);
}

再创建一个mapper,同名的mapper.xml然后把名称空间指向上面这个接口

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sunofbeaches.dao.EmployeeAction">


    <!--void insert(EmployeeBean employeeBean);-->
    <insert id="insert">
        INSERT  INTO tbl_employee(last_name,email,gender) VALUES (#{lastName},#{email},#{gender})
    </insert>

    <!--void update(EmployeeBean employeeBean);-->
    <update id="update">
        UPDATE tbl_employee SET last_name=#{lastName} , email=#{email} , gender=#{gender} WHERE id = #{id}
    </update>

    <!--void delete(EmployeeBean employeeBean);-->
    <delete id="delete">
        delete FROM tbl_employee WHERE id=#{id}
    </delete>
</mapper>

测试:

package com.sunofbeaches.test;

import com.sunofbeaches.beans.EmployeeBean;
import com.sunofbeaches.dao.EmployeeAction;
import com.sunofbeaches.utils.LogUtils;
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 java.io.InputStream;

/**
 * Created by TrillGates on 18/7/21.
 */
public class DBTest {

    private static final String TAG = "DBTest";

    public static void main(String[] args) throws Exception {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        LogUtils.d(TAG, "sqlSessionFactory " + sqlSessionFactory);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        try {
            EmployeeAction mapper = sqlSession.getMapper(EmployeeAction.class);
            EmployeeBean bean = new EmployeeBean();
//            bean.setLastName("Bill");
//            bean.setEmail("bill@gmail.com");
//            bean.setGender("1");

            //mapper.insert(bean);
//            bean.setLastName("Test");
//            bean.setEmail("test@gmail.com");
//            bean.setGender("0");
            bean.setId(1);

          //  mapper.update(bean);

            mapper.delete(bean);

            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }

    }
}

结果:

Snip20181209_60

4.1.Mapper接口方法里的参数

我们的xml映射文件里的sql语句是怎么获取到参数的呢?

比如说,我们通过id去删除employee

 

 <!--    void deleteById(Integer id);-->
    <delete id="deleteById">
        DELETE FROM tbl_employee WHERE id=#{id}
    </delete>

 

我们通过一个#{字段名称}获取到id值

其实mybatis是这样子处理的

当方法是一个参数的时候,直接获取即可。如上,如果我们使用


    <!--    void deleteById(Integer id);-->
    <delete id="deleteById">
        DELETE FROM tbl_employee WHERE id=#{idasdfasdf}
    </delete>

#{随便输入东西}也是可以获取到id的值的,可以去试一下哈,这里我就不试了,再删除我就没内容了哈。

当方法多个参数的时候:


    <!-- void getEmployeeByIdAndLastName(Integer id, String lastName);-->
    <select id="getEmployeeByIdAndLastName" resultType="com.sunofbeaches.beans.EmployeeBean">
        SELECT * FROM tbl_employee WHERE id=#{id} and last_name=#{lastName}
    </select>

假如我们这么写,肯定报错:

Snip20181209_61

那怎么办呢?看报错信息,有两个param呢!

我们改成这样子:

    <!-- void getEmployeeByIdAndLastName(Integer id, String lastName);-->
    <select id="getEmployeeByIdAndLastName" resultType="com.sunofbeaches.beans.EmployeeBean">
        SELECT * FROM tbl_employee WHERE id=#{param1} and last_name=#{param2}
    </select>

Snip20181209_62

查询出来了,可是我用的参数是param1,param2,不好看呀,怎么办呢?

其实呀,多个参数的时候 ,mybatis把参数封装成了一个集合,key默认是param1,param2

我们也是可以指定的,为了方便起见,我们可以这么做:

package com.sunofbeaches.dao;

import com.sunofbeaches.beans.EmployeeBean;
import org.apache.ibatis.annotations.Param;

/**
 * Created by TrillGates on 2018/12/9.
 */
public interface EmployeeAction {

    void insert(EmployeeBean employeeBean);

    void update(EmployeeBean employeeBean);

    void delete(EmployeeBean employeeBean);

    void deleteById(Integer id);

    EmployeeBean getEmployeeByIdAndLastName(@Param("id") Integer id, @Param("lastName") String lastName);
}

 

映射文件写成这样子:

    <!-- void getEmployeeByIdAndLastName(Integer id, String lastName);-->
    <select id="getEmployeeByIdAndLastName" resultType="com.sunofbeaches.beans.EmployeeBean">
        SELECT * FROM tbl_employee WHERE id=#{id} and last_name=#{lastName}
    </select>

 

再来试试看运行结果如何:

Snip20181209_63

查到了吧!

还可以怎么解决呢?多个参数转成一个参数呗,保存成一个Map对不对。反正都要转成Map集合的。

那我们这样写好了:

    EmployeeBean getEmployeeByMap(Map<String, Object> map);

 


    <!-- EmployeeBean getEmployeeByMap(Map<String, Object> map);-->
    <select id="getEmployeeByMap" resultType="com.sunofbeaches.beans.EmployeeBean">
        SELECT * FROM tbl_employee WHERE id=#{id} and last_name=#{lastName}
    </select>

Snip20181209_64

假设参数是List怎么获取呢?如果是Array下面的参数怎么获取呢?

举例子吧:

    EmployeeBean getEmployeeByList(List<Object> params);

映射文件这样写:


    <!--    EmployeeBean getEmployeeByList(List<String> params);-->
    <select id="getEmployeeByList" resultType="com.sunofbeaches.beans.EmployeeBean">
        SELECT * FROM tbl_employee WHERE id=#{list[0]} and last_name=#{list[1]}
    </select>

运行结果:

EmployeeBean{id=3, lastName='Bill', email='bill@gmail.com', gender='1'}

数组同理的,这里就不写去写例子了。

 

 

 

7K
为您推荐
各种观点