创建一个简单的Mybatis项目

一、创建一个简单的Mybatis项目

浅说一下mybatis的原理(目前理解):代替了原来Dao层(数据持久层)每次使用都需要connection连接数据库的操作,使用xml文件的方式,配置一次数据库的连接,之后使用Dao层的方法不再需要专门连接;同时将Dao层中实现接口的方法(sql语句)改用为xml文件实现

1.mybatis在线文档

https://mybatis.net.cn/getting-started.html

2.创建一个Maven项目

3.在pom.xml加入Maven依赖

<!--mybatis依赖-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
</dependency>

<!--mysql-connector依赖-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

<!--单元测试的依赖,方便调试-->
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>

4.在resource中创建mybatis配置文件

<!--
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="com.mysql.cj.jdbc.Driver"/>
          <!--url在idea连接数据库时查看-->
        <property name="url" value="jdbc:mysql://localhost:3306"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
          
      </dataSource>
    </environment>
  </environments>
    
    <!--每个Mapper.xml(之后会创建)都需要在此处注册-->
     <!--
     <mappers>
        <mapper resource=""/>
     </mappers>
        -->
</configuration>

5.整体包的结构如下

6.接下来创建utils包和MybatisUtils类

MybatisUtils类的作用是利用SqlSessionFactory创建一个SqlSession类,用于操作之后接口中的方法

package com.Gw.utils;

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.IOException;
import java.io.InputStream;

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
/*
	简单来说只用三句话,意思是从resource资源文件中以流形式得到xml配置文件,创建SqlSessionFactory,并创建SqlSession
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
*/
    static {
        //此处填写刚才的配置文件
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

7.编写Dao层

先说明一下实体类包pojo中的User类,实际由id、name、pwd组成,有对应的set、get方法和构造函数

本文省略了与数据库连接的部分,与数据库中数据的创建,给实例图读者自行创建、连接

在UserMapper中创建sql语句的接口

package com.Gw.dao;

import com.Gw.pojo.User;
import java.util.List;

public interface UserMapper {
    List<User> getUserList();
    //根据id查询用户
    User getUserById(int id);

    //插入用户
    void addUser(User user);

    //修改用户
    int updateUser(User user);

    //删除一个用户
    int deleteUser(int id);
}

在UserMapper.xml中实现对应的sql查询

<?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">

<!--namespace为名空间,对应着接口的位置-->
<mapper namespace="com.Gw.dao.UserMapper">
    <!--select查询语句,id对应着接口中的方法名,在select中对应sql语句   -->
    <select id="getUserList" resultType="com.Gw.pojo.User">
        select * from mybatis.user
    </select>
    <select id="getUserById" parameterType="int" resultType="com.Gw.pojo.User">

        select * from mybatis.user where id=#{id}
    </select>
    <insert id="addUser" parameterType="com.Gw.pojo.User">
        insert into mybatis.user(id, name, pwd) values (#{id}, #{name}, #{pwd});
    </insert>
    <update id="updateUser" parameterType="com.Gw.pojo.User">
        update mybatis.user set name =#{name},pwd=#{pwd} where id = #{id};
    </update>
    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>
</mapper>

<!--标签中有select、insert、update、delete语句,与sql中的对应-->

<!--说明一下标签中关键字的含义(与原Dao层的实现方法对应更好理解),id为接口中的方法名,parameterType传入方法的参数类型,resultType表示返回值类型,#{}表示从程序中(方法参数中)获取变量-->

<!--此例中当传进来对象为User时,在获取变量时只可以用#{id},#{name},#{pwd},如果想更改参数的名字,可以传进一个map对象,将原对象的变量名改为map中的key即可-->

8.测试执行

在test包中创建与main包中的相同结构,创建UserMapperTest类,具体参考5

使用junit进行测试

说明:在使用UserMapper中的方法时,需要先通过MybatisUtils创建SqlSession,再利用SqlSession通过UserMapper的接口获得mapper映射,之后就可以通过mapper对象调用UserMapper中的方法

package com.Gw.Dao;

import com.Gw.dao.UserMapper;
import com.Gw.pojo.User;
import com.Gw.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.jupiter.api.Test;

import java.util.List;

public class UserMapperTest {

    @Test
    public void test(){
        //第一步:获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //第二步:执行sql语句
        //方法一:getMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();

        //方法二:不推荐
        List<User> list = sqlSession.selectList("com.Gw.dao.UserDao.getUserList");

        for (User user : userList) {
            System.out.println(user.getId() + " " + user.getName() + " " + user.getPwd());
        }
        sqlSession.close();
    }
    @Test
    public void getUserById(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.getUserById(1).getName());
    }
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setId(4);
        user.setName("小芳");
        user.setPwd("123456");
        mapper.addUser(user);

        //提交事务,修改完一定要提交事务
        sqlSession.commit();

        sqlSession.close();
    }
    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser(new User(1,"李华","456789"));
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUser(2);
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    public void getUserLike(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userLike = mapper.getUserLike("%李%");
        for (User user : userLike) {
            System.out.println(user.getName() + " " + user.getPwd());
        }
        sqlSession.close();
    }
}

二、配置解析

在config-mybatis.xml中必须按照此顺序设置
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
    environment(环境变量)
        transactionManager(事务管理器)
        dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

1.environment

1.事务管理器(transactionManager)

在Mybatis中有两种类型的事务管理器,JDBC和MANAGED

  • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
  • MANAGED – 这个配置几乎没做什么。

如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

2.数据源(dataSource)

  • POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
  • UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。
  • JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。

2.属性(properties)

  • 可以引入外部文件db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&characterEncoding=UTF-8
username=root
password=123456

使用时需在mybatis-config.xml加入properties标签

<properties resource="db.resource"/>
<!--然后可直接调用-->
<property name="username" value="${username}"></property>
  • 可以在xml中插入properties标签
<properties>
	<property name="username" value="root"/>
</properties>
  • 当二者都存在时,先使用外部配置文件

3.类型别名(typeAliases)

简化使用实体类中的类名

<!--为java类起别名-->
<typeAliases>
    <typeAlias alias="User" type="com.Gw.pojo.User"/>
</typeAliases>

<!--为包起别名,包内的类可以小写直接用,不用再写一长串-->
<typeAliases>
    <package name="com.Gw.pojo"/>
</typeAliases>

在实体类比较少的时候使用第一种,多的时候使用第二种;

第一种可以自定义别名,第二种自定义别名则需要在实体上加注解

@Alias("user")
public class user{}

4.设置(settings)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

重点掌握

设置名 描述 有效值 默认值
cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 true | false false
useGeneratedKeys 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 true | false False
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置

5.其他配置

typeHandlers(类型处理器)
objectFactory(对象工厂)

插件(plugin)

  • mybatis-generator-core
  • mybatis-plus-boot-starter
  • 通用mapper

6.映射器(mappers)

1.原始方式

<mappers>
    <mapper resource="com/Gw/dao/UserMapper.xml"/>
</mappers>

2.使用class的文件绑定注册

<mappers>
	<mapper class="com.Gw.dao.UserMapper"/>
</mappers>

3.通过package

<mappers>
	<package name="com.Gw.dao"/>
</mappers>

注意:2、3的接口和它的Mapper配置文件必须同名并且接口和它的配置文件必须在一个包下

7.作用域和生命周期

不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。

SqlSessionFactoryBuilder

  • 一旦创建了 SqlSessionFactory,就不再需要它了
  • 局部变量

SqlSessionFactory

  • 可以想象成数据库连接池

  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。

  • SqlSessionFactory 的最佳作用域是应用作用域。

  • 在应用运行期间不要重复创建多次有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

SqlSession

  • 每一个独享一个线程,与连接池连接

  • 每个线程都应该有它自己的 SqlSession 实例。

  • 它的最佳的作用域是请求或方法作用域。

  • 考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它

总结:

mapper就相当于一个业务

三、解决实体类和数据库名字不一致的问题

pojo中为password

数据库中为pwd

解决方法:

  • 起别名
<select id="getUserById" resultType="com.Gw.pojo.User">
	select id, name, pwd as password from mybatis.user where id = #{id}
</select>

结果集映射(resultMap)简介

  • resultMap 元素是 MyBatis 中最重要最强大的元素。
  • ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
<!--使用举例-->

<!--建立名为UserMap的结果映射,其中column表示数据库中的字段,property表示实体类中的属性-->
<resultMap id="UserMap" type="User">
    <result column="pwd" property="password"></result>
</resultMap>

<!--resultMap指定结果映射为UserMap-->
<select id="getUserById" parameterType="int" resultMap="UserMap">
    select * from mybatis.user where id=#{id}
</select>
posted @ 2022-04-19 17:31  CDUT的一只小菜鸡  阅读(180)  评论(0编辑  收藏  举报