day21-MyBatis简介(千峰逆战)

1、简介
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation
迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。
MyBatis 支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC代码和手
动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将
接口和 Java的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
2、添加依赖
使用MyBatis与数据库进行交互需要添加两个依赖:一个是数据库的驱动,不同的数据库需要不同的驱动。另一个是MyBatis的依赖:

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
上面添加的数据库依赖是MySQL的,具体看你用的是什么数据库就添加对应的依赖就可以了。

3、xml文件配置
mybatis.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="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="huwenlong"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper.xml"/>
</mappers>
</configuration>
mybatis.xml文件位于resources目录下,它的根节点是configuration,环境默认为开发环境,数据源为连接池,MyBatis自带连接池。四个属性根据自己使用的数据库进行设置,我使用的是MySQL 8.0所以驱动是com.mysql.cj.jdbc.Driver,如果你使用的是8.0以下版本则应该是com.mysql.jdbc.Driver。然后就是数据库名、用户名与密码,填写对应的就好。最后一个mappers是映射关系,resource是一个文件。

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.qianfeng.pojo.User">
<select id="selectUsers" resultType="com.qianfeng.pojo.User">
select * from user
</select>
<select id="selectUser" resultType="com.qianfeng.pojo.User">
select * from user where userName = #{userName} and password = #{password}
</select>
<select id="selectUserCount" resultType="int">
select count(1) from user
</select>
<select id="selectUsersByPage" resultType="com.qianfeng.pojo.User">
select * from user limit #{startIndex},#{pageSize}
</select>
<insert id="saveUser" >
insert into user values (default ,#{userName},#{password},#{age},#{address})
</insert>
<delete id="deleteUser">
delete from user where id = #{id}
</delete>
<update id="updateUser">
update user set userName = #{userName},password = #{password},age = #{age},address = #{address} where id = #{id}
</update>
</mapper>
这个文件最重要的是namespace以及每一个项目的id,前者规定了命名空间,可以自己定义,后者是区分每一条语句的id,也可以自己定义,但要保证namespace+id全局唯一,使用的时候要对应。#{}包裹的是占位符,我们使用的时候需要传参。resultType是结果类型。

4、编写测试代码
User.java

package com.qianfeng.pojo;

public class User {
private int id;
private String userName;
private String password;
private int age;
private String address;

public User() {
}

public User(int id, String userName,String password, int age, String address) {
    this.password = password;
    this.id = id;
    this.userName = userName;
    this.age = age;
    this.address = address;
}

public int getId() {
    return id;
}

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

public String getUserName() {
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

@Override
public String toString() {
    final StringBuilder sb = new StringBuilder("User{");
    sb.append("id=").append(id);
    sb.append(", userName='").append(userName).append('\'');
    sb.append(", password='").append(password).append('\'');
    sb.append(", age=").append(age);
    sb.append(", address='").append(address).append('\'');
    sb.append('}');
    return sb.toString();
}

}
User类是一个POJO,有5个成员,每个成员要与数据库的user表的每个字段一一对应。

UserTest.java

package com.qianfeng.pojo;

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.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;

public class UserTest {
private SqlSessionFactory sf = null;
private SqlSession ss = null;
@Before
public void setUp() throws Exception {
sf = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml"));
ss = sf.openSession(true);
}
@Test
public void testSelectUsers(){
List<User> users = ss.selectList("com.qianfeng.pojo.User.selectUsers");
for (User user : users) {
System.out.println(user);
}
}

@Test
public void testSelectUser(){
    User user  = new User();
    user.setUserName("王五");
    user.setPassword("888888");
    User user1 = ss.selectOne("com.qianfeng.pojo.User.selectUser",user);
    System.out.println(user1);
}

@Test
public void testSelectUserCount(){

    int i = ss.selectOne("com.qianfeng.pojo.User.selectUserCount");
    System.out.println(i);
}

@Test
public void testSelectUsersByPage(){
    Map<String,Integer> map = new HashMap<>();
    map.put("startIndex",0);
    map.put("pageSize",5);
    List<User> users = ss.selectList("com.qianfeng.pojo.User.selectUsersByPage",map);
    for (User user : users) {
        System.out.println(user);
    }
}
@Test
public void saveUser(){
    User user = new User(0,"李四","1234567",20,"湖北省武汉市");
    int i = ss.insert("com.qianfeng.pojo.User.saveUser",user);
    System.out.println(i);
}
@Test
public void deleteUser(){
    int i = ss.delete("com.qianfeng.pojo.User.deleteUser",1);
    System.out.println(i);
}
@Test
public void updateUser(){
    User user = new User(2,"王五","888888",21,"安徽省合肥市");
    int i = ss.update("com.qianfeng.pojo.User.updateUser",user);
    System.out.println(i);
}
@After
public void tearDown() throws Exception {
    if(ss!=null){
        ss.close();
        ss = null;
    }
}

}
这个测试类实现了MyBatis的增删改查操作,由于创建SqlSessionFactory与SqlSession与销毁SqlSession的操作每个方法都需要执行,所以把它们单独提出来分别放在setUp与tearDown方法中。

SqlSession中有很多方法可以用于数据库的增删改查操作,每个方法的第一个参数都是String类型statement,这个值是我们之前在mapper.xml文件中的"namespace.id"。第二个参数是一个Object类型的对象,用于一些条件,比如条件查询,插入值等,select方法还有第三个参数RowBounds参数,这个参数用于分页。

5、与Hibernate的比较
两者都是非常流行的ORM框架(Object Relational Mapping对象关系映射)。Hibernate的O/R Mapping实现了POJO 和数据库表之间的映射,以及SQL的自动生成和执行。相对Hibernate“O/R”而言,Mybatis 是一种“Sql Mapping”的ORM实现
Hibernate的真正掌握要比MyBatis困难,Hibernate比mybatis更加重量级一些。
Mybatis需要我们手动编写SQL语句,回归最原始的方式,所以可以按需求指定查询的字段,提高程序的查询效率。Hibernate也可以自己写SQL语句来指定需要查询的字段,但这样破坏了Hibernate封装以及简洁性。
MyBatis由于所有的sql语句都是依赖数据库书写的,所以扩展性迁移性比较差。Hibeinate通用性比较强。
两者的缓存有相同之处:二级缓存除了采用系统默认的缓存机制外,都可以通过实现你自己的缓存或为其他第三方缓存方案,创建适配器来完全覆盖缓存行为,也有不同之处:Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再在具体的表-对象映射中配置是那种缓存。MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容