Mybatis框架——快速入门

目录

1、Mybatis概述

1.1、ORM概述

1.2、常见的ORM框架

1.3、Mybatis优缺点

1.4、Mybatis的工作原理

2、Mybatis快速入门

2.1、数据库准备

2.2、导入依赖

2.3、编写全局配置文件

2.4、jdbc.properties配置文件

2.5、pojo实体类

2.6、实现步骤

2.7、测试

2.8、添加日志

3、Mybatis实现CRUD

3.1、创建dao层

3.2、编写sql映射文件UserMapper.xml

3.3、加载sql映射文件

3.4、编写测试类

4、解决数据库字段名和实体类属性名不一致的问题

4.1、sql语句起别名

4.2、全局配置开启驼峰匹配

5、优化接口测试类

5.1、删除UserDaoImpl类

5.2、修改UserMapper.xml文件中的namespace

5.3、修改包名和接口名

5.4、修改测试类

6、mybatis-config.xml配置

6.1、typeAliaseso类别名

6.2、environments环境

6.3、mappers映射器

7、mapper.xml映射文件

7.1、select标签

7.2、insert标签

7.3、update标签

7.4、delete标签


1、Mybatis概述

1.1、ORM概述

在使用JDBC 的时候,我们通常将数据直接返回,但现在也会将数据封装到实体类对象中,由对象携带数据。这样操作的时候,可以通过操作对象的方式操作数据。但是手写这类代码通常是繁琐的、重复的,如果有自动完成这些功能的程序就好了。

ORM(Object-Relational-Mapping):是对象关系映射的意思,它是一种思想,是指将数据库中的每一行数据用对象的形式表现出来。可以将 ORM 简单理解为上面我们提出的,可以自动将对象与数据进行映射的技术。

1.2、常见的ORM框架

Hibernate: 完全ORM映射框架

优点:

1、简化了整个jdbc操作过程

2、对于开发者来说不需要关心sql了,只需要去操作对象就可以了,hibernate可以帮我们自动生成所需要的sql

3、代码移植性比较好,通过hibernate操作db都是通过操作对象来进行的,而hibernate会根据我们的操作和db的类型生成符合各种db要求的sql,如果我们需要切换db的类型,hibernate会自动适应,对于开发者业务代码来说不需要做任何业务代码上的调整

4、开发效率比较高

缺点:

1、sql优化比较艰难,各种操作最终发给db的sql是由hibernate自动生成的,对于开发者来说如果想干预最终需要执行的sql,相对来说比较困难

2、hibernate入门比较容易,但是想成为高手学习成本比较高

3、对于复杂的动态sql,代码中也需要写很多判断进行组装,动态sql这块的支持比较欠缺

如果做一些简单的系统,开发周期也比较紧急,对sql的优化要求也不是很高,可以使用hibernate。

JdbcTemplate :半自动的ORM框架

jdbcTemplate是在Spring框架的基础上开发的一个jdbc框架,所以对spring是有依赖的,它对jdbc做了封装,隐藏了各种重复的操作,使用时只需传入:需要执行的sql、参数以及对于结果如何解析的程序就可以了,使用起来还是很方便的,但是面对与动态sql,它也是无能为力了。整体上来说,jdbctemplate相对于纯jdbc隐藏了很多重复性的操作,对于sql的写法和结果的组装上完全交给了开发者自己去控制,在系统中使用也可以帮助我们节约很多时间,而且学习相当简单.  

MyBatis:半自动的化的ORM框架

MyBatis是一个半自动化的orm框架,为什么说是半自动化的呢,因为他需要我们自己去写sql,而他做的更好的地方就是动态sql的支持上面,而上面说的各种技术,面对与动态sql只能自己写很多判断去组装sql,而这些判断和组装在mybatis中实现起来就非常简单了,完全由mybatis去帮我们实现了。mybatis将sql交由开发者去控制,所以在sql的优化方面,开发者可以随心所欲,也就是说mybatis将重复性的工作优化到了极致:操作db的过程、动态sql的拼装、结果和对象的映射,这些mybatis都帮我们实现的很好,而让我们将更多的经历花在sql的写法和优化上面,所以毫无疑问mybatis使用人数和公司也是最多的。

1.3、Mybatis优缺点

MyBatis官网地址:mybatis – MyBatis 3 | 简介

1、mybatis是一个半自动化的持久层框架。
2、mybatis封装了jdbc的很多细节,开发者只需要关注sql本身,无需关注注册驱动、获取连接等操作。
3、mybatis使用ORM思想来对结果集一个封装。

优点:

1、简单易学,容易上手(相比于 Hibernate)基于SQL编程。
2、消除了JDBC大量冗余的代码,不需要手动开关连接。
3、很好的与各种数据库兼容(因为 MyBatis 使用JDBC来连接数据库,所以只要JDBC 支持的数据库 MyBatis 都支持,而JDB提 供了可扩展性,所以只要这个数据库有针对Java的jar包就可以就可以与 MyBatis 兼容),开发人员不需要考虑数据库的差异性。
4、提供了很多第三方插件(分页插件 / 逆向工程)。

5、能够与Spring很好的集成。
6、如果使用映射文件的话,可以让代码和配置文件完全分离。只要方法的定义没有改变,那么只需要修改配置文件就可以达到修改的目的。 

缺点:

SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。
SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

1.4、Mybatis的工作原理

Mybatis框架——快速入门_第1张图片 Mybatis的工作原理如上图,需要首先创建一个Mybatis的全局配置文件mybatis-config.xml(名称不固定,可以随便起),其次是多个mapper.xml配置文件用来书写sql语句,为了能够使用这些配置文件,我们需要通过SqlSessionFactory创建一个SqlSession对象(这个对象是Mybatis的核心对象,CRUD都是通过该对象进行调用),后通过executor底层执行器执行sql语句,得到结果集返回。

2、Mybatis快速入门

2.1、数据库准备

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `sex` char(1) DEFAULT NULL,
  `email` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

自行添加数据,这是我的数据 

 Mybatis框架——快速入门_第2张图片

2.2、导入依赖

此次演示使用的是Maven工程,所以需要导入Mybatis的坐标依赖,以及mysql数据库连接依赖,还有一个就是lombok依赖,用来使用注解生成实体类的set/get方法。

 
        
        
            org.mybatis
            mybatis
            3.5.6
        

        
        
            mysql
            mysql-connector-java
            5.1.18
        

        
        
            org.projectlombok
            lombok
            1.16.18
            provided
        

        
        
            org.junit.jupiter
            junit-jupiter-api
            RELEASE
            compile
        
        
            junit
            junit
            4.11
        
    

2.3、编写全局配置文件

mybatis-config.xml是Mybatis的全局配置文件,也是Mybatis里很重要的配置文件





    
    

    
    
        
            
            
                
                
                
                
            
        
    
    
    
        
    

注意事项:properties标签是引入jdbc.properties数据库连接配置文件的,environments标签是配置环境,里面就是获取mysql的连接配置,固定模版,直接粘贴即可。mapper标签是用来获取映射文件的路径。

2.4、jdbc.properties配置文件

创建jdbc.properties配置文件放到resources包下

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///数据库名
username=root
password=你的数据库密码

切记一定要把所有的配置文件放到resources包下,我是为了方便整理,所以创建了一个mapper包,根据个人喜好,也可不用创建,注意:如果创建了mapper包,在mapper映射路径中切记要加上mapper

Mybatis框架——快速入门_第3张图片

Mybatis框架——快速入门_第4张图片

2.5、pojo实体类

@Data
public class User {
    private int id;
    private String username;
    private String password;
    private int age;
    private String sex;
    private String email;
}

2.6、实现步骤

创建一个测试类

public class MybatisDemo{
    public static void main(String[] args) throws IOException {
        //获取核心配置文件
        String resource="mybatis-config.xml";
        //加载配置文件
        InputStream inputStream= Resources.getResourceAsStream(resource);
        //构建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        //构建Sqlsession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行sql  第一个参数为xml文件中namespace名称,第二个参数就是参数值id
        User user = sqlSession.selectOne("UserMapper.selectById",8);
        System.out.println(user);
    }
}

创建对应的sql映射配置文件selectUserMapper.xml






    
    

把之前的mybatis-config.xml全局配置文件中最后一行的mapper标签的路径填写为sql映射文件的路径(切记不要忘了)



    

2.7、测试

运行测试类,得到了sql语句查询的结果

2.8、添加日志

然而这种直接得出结果的方式并不友好,不方便看到运行的过程,所以我们需要导入log4j坐标,可以在运行的时候查看到运行日志,方便调试程序。



     org.slf4j
     slf4j-log4j12
     1.6.4

在resources包下创建log4j.properties配置文件

固定模版,直接粘贴复制即可

log4j.rootLogger=DEBUG,A1
log4j.logger.org.mybatis=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

再次运行测试类

可以看到这次就能看到具体的sql语句,以及传递的参数,还有返回结果的个数

Mybatis框架——快速入门_第5张图片

3、Mybatis实现CRUD

3.1、创建dao层

Mybatis框架——快速入门_第6张图片

public interface UserDao {
      /**
       * @description:根据id查询用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:45
       * @param: []
       * @return: cn.itssl.pojo.User
       **/
      User queryUserById(int id);
      /**
       * @description:查询所有用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:45
       * @param: []
       * @return: java.util.List
       **/
      List queryUserAll();
      /**
       * @description:删除用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:46
       * @param: []
       * @return: void
       **/
      void deleteUserById(int id);
      /**
       * @description:添加用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:46
       * @param:
       * @return:
       **/
      void addUser(User user);
      /**
       * @description:根据id修改用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:47
       * @param: [id]
       * @return: void
       **/
      void updateUser(User user);
}
public class UserDaoImpl implements UserDao {
    private SqlSession sqlSession;

    //通过有参构造获取sqlSession对象
    public UserDaoImpl(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    /**
     * @description:根据id查询用户
     * @author: Shenshuanglong
     * @date: 2022/10/14 0014 15:37
     * @param: [id]
     * @return: cn.itssl.pojo.User
     **/
    public User queryUserById(int id) {
        return sqlSession.selectOne("UserMapper.queryUserById", 8);
    }

    /**
     * @description:查询所有用户
     * @author: Shenshuanglong
     * @date: 2022/10/14 0014 15:37
     * @param: []
     * @return: java.util.List
     **/
    public List queryUserAll() {
        return sqlSession.selectList("UserMapper.queryAllUser");
    }

    /**
     * @description:根据id删除用户
     * @author: Shenshuanglong
     * @date: 2022/10/14 0014 15:37
     * @param: [id]
     * @return: void
     **/
    public void deleteUserById(int id) {
        sqlSession.delete("UserMapper.deleteUser",id);
    }

    /**
     * @description:添加用户
     * @author: Shenshuanglong
     * @date: 2022/10/14 0014 15:43
     * @param: [user]
     * @return: void
     **/
    public void addUser(User user) {
        sqlSession.insert("UserMapper.addUser", user);
    }

    /**
     * @description:根据id删除用户
     * @author: Shenshuanglong
     * @date: 2022/10/14 0014 15:43
     * @param: [id]
     * @return: void
     **/
    public void updateUser(User user) {
        sqlSession.update("UserMapper.updateUser",user);
    }
}

3.2、编写sql映射文件UserMapper.xml




    

    

    
        delete
        from t_user
        where id = #{id}
    
    
        insert into t_user
        values (null, #{username}, #{password}, #{age}, #{sex}, #{email})
    
    
        update t_user
        set username=#{username},
            password=#{password},
            age=#{age},
            sex=#{sex},
            email=#{email} where id=#{id};
    

3.3、加载sql映射文件



    

3.4、编写测试类

public class MybatisDemo2 {
    private UserDao userDao;
    private SqlSession sqlSession;
    //在执行test测试之前一定会执行Before
    @BeforeEach
    public void setUp() throws IOException {
        //获取核心配置文件
        String resource = "mybatis-config.xml";
        //加载配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //构建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //构建Sqlsession对象  这里传递一个true为了使数据库开启自动事务
        sqlSession = sqlSessionFactory.openSession(true);
        //把sqlSession对象传递至dao层
        userDao = new UserDaoImpl(sqlSession);
    }
    
    //根据id查询
    @Test
    public void queryUserById() {
        User user = this.userDao.queryUserById(8);
        System.out.println(user);
    }
    //查询所有
    @Test
    public void queryAllUser(){
        List users = this.userDao.queryUserAll();
        for (User user : users) {
            System.out.println(user);
        }
    }
    //删除用户
    @Test
    public void deleteUserById(){
        this.userDao.deleteUserById(7);
    }
    //添加用户
    @Test
    public void addUser(){
        User user=new User();
        user.setUsername("刘备");
        user.setPassword("1234");
        user.setAge(23);
        user.setSex("男");
        user.setEmail("[email protected]");
        this.userDao.addUser(user);
    }
    //修改用户
    @Test
    public void updateUser(){
        User user=new User();
        user.setId(10);
        user.setUsername("张飞");
        user.setPassword("147852");
        user.setAge(22);
        user.setSex("男");
        user.setEmail("[email protected]");
        this.userDao.updateUser(user);
    }
}

4、解决数据库字段名和实体类属性名不一致的问题

可能在以后的开发中存在这样的问题,就是数据库在创建字段时候按照数据库的命名规则用户名命名为user_name,而在Java实体类中变量值按照大驼峰命名为userName,这样就会造成一种查询不到用户名的问题,因为名字不一致。

4.1、sql语句起别名

就是在查询语句中把user_name起别名,这样就可以获取到查询的用户名,不过这种方式太过麻烦,如果查询语句上千条,那岂不是一条一条的添加(太麻烦,不推荐)

Select  * , user_name as username  from t_user;

4.2、全局配置开启驼峰匹配

最快速有效的方式,Mybatis为我们提供了一个驼峰匹配的属性,所以需要我们在全局配置文件中进行手动配置,开启驼峰匹配

在mybatis-config.xml文件中加入下面代码

  
    
        
    

注意:一定要按照xml文件的定义顺序进行书写,否则出现异常,按照异常提示,从左向右是标签定义的先后顺序。

5、优化接口测试类

5.1、删除UserDaoImpl类

我们是否有这样的一个问题,就是在dao的实现类还要通过调用sqlsession的方法,然而真正实现CRUD功能却是在sql映射文件中,这样不是感觉多此一举吗,所以,为了方便我们开发,需要把实现类进行删除,直接由接口对接UserMapper.xml的sql映射文件。

Mybatis框架——快速入门_第7张图片

5.2、修改UserMapper.xml文件中的namespace

在之前有实现类的时候,namespace我们是随便起的名字,然而现在就不能随便起了,需要填写UserDao接口的路径,因为只有这样才能把userDao接口与UserMapper.xml关联起来,之前是通过实现类里调用sqlsession的方法来关联的。

修改前:

修改后:

5.3、修改包名和接口名

为了方便后面的理解,我们以后就不能使用dao来做接口的名称了,就用mapper来替代。记得UserMapper里面的路径也改为mapper,修改类名时应该会自动替换,如果没有则进行手动修改。

5.4、修改测试类

可以看到,当删除实现类后,UserDaoImpl的有参构造就报错了,我们就不能使用该方法了,那么就使用动态代理来获取UserDao。

Mybatis框架——快速入门_第8张图片

 修改后的测试类:

public class MybatisDemo2 {
    private UserMapper userMapper;
    private SqlSession sqlSession;

    @Before
    public void setUp() throws IOException {
        //获取核心配置文件
        String resource = "mybatis-config.xml";
        //加载配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //构建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //构建Sqlsession对象
        sqlSession = sqlSessionFactory.openSession(true);
        //把sqlSession对象传递至dao层
        // userDao = new UserDaoImpl(sqlSession);
        //使用动态代理
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void queryUserById() {
        User user = this.userMapper.queryUserById(8);
        System.out.println(user);
    }

    @Test
    public void queryAllUser(){
        List users = this.userMapper.queryAllUser();
        for (User user : users) {
            System.out.println(user);
        }
    }
    @Test
    public void deleteUserById(){
        this.userMapper.deleteUserById(8);
    }

    @Test
    public void addUser(){
        User user=new User();
        user.setUsername("jack");
        user.setPassword("1234");
        user.setAge(23);
        user.setSex("男");
        user.setEmail("[email protected]");
        this.userMapper.addUser(user);
    }

    @Test
    public void updateUser(){
        User user=new User();
        user.setId(10);
        user.setUsername("rose");
        user.setPassword("147852");
        user.setAge(22);
        user.setSex("女");
        user.setEmail("[email protected]");
        this.userMapper.updateUser(user);
    }
}

修改后的接口: 

public interface UserMapper {
      /**
       * @description:根据id查询用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:45
       * @param: []
       * @return: cn.itssl.pojo.User
       **/
      User queryUserById(int id);
      /**
       * @description:查询所有用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:45
       * @param: []
       * @return: java.util.List
       **/
      List queryAllUser();
      /**
       * @description:删除用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:46
       * @param: []
       * @return: void
       **/
      void deleteUserById(int id);
      /**
       * @description:添加用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:46
       * @param:
       * @return:
       **/
      void addUser(User user);
      /**
       * @description:根据id修改用户
       * @author: Shenshuanglong
       * @date: 2022/10/14 0014 14:47
       * @param: [id]
       * @return: void
       **/
      void updateUser(User user);
}

 修改后的UserMapper.xml文件




    

    

    
        delete
        from t_user
        where id = #{id}
    
    
        insert into t_user
        values (null, #{username}, #{password}, #{age}, #{sex}, #{email})
    
    
        update t_user
        set username=#{username},
            password=#{password},
            age=#{age},
            sex=#{sex},
            email=#{email} where id=#{id};
    

注意:因为没有了实现类,在关联xml映射文件之后需要让接口的方法名和sql映射文件中每条sql的id唯一标识的名称保持一致,否则会出现报错!!

6、mybatis-config.xml配置

6.1、typeAliaseso类别名

可以发现,我们每次写查询语句的时候,必须要写一个resultType来指定一下返回值类型,然而每次都得写路径,太过于麻烦,那么Mybatis提供一个typeAliaseso类别名来简化开发。

Mybatis框架——快速入门_第9张图片

 
        
        
        
        
 

注意:以上方式选其一即可,两个同时存在会出现冲突。

配置完之后,我们再修改UserMapper.xml文件,把原有的路径去掉,只留下实体类的类名

Mybatis框架——快速入门_第10张图片

6.2、environments环境

其实我们后开发中,不止一个环境,例如:开发环境,测试环境,发布环境等,可以在项目中设置多环境

 
    

        
        
            
            
                
                
                
                
            
        

        
        
            
            
                
                
                
                
            
        
    

配置完之后,我们在测试类的setUp方法中加入环境。 

@Before
    public void setUp() throws Exception {
        //指定核心配置文件的位置
        String resource = "mybatis-config.xml";
        //加载核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //构建sqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"dev");//使用指定环境
        //获取SqlSession对象,SqlSession可以操作crud
        sqlSession = sqlSessionFactory.openSession();

        //动态代理
        userMapper = sqlSession.getMapper(UserMapper.class);

    }

6.3、mappers映射器

其实在全局配置里面的mappers不只有resource一种获取映射文件的方式,还有其余两种,一个是class属性来获取,需要用.来分隔。另外一种就是通过导包的方式,但是必须满足两个条件:

1、接口名要与mapper的名一致
2、接口类要与mapper.xml文件放在同一目录中

 
    
        
        

        
        

        
        
    

7、mapper.xml映射文件

7.1、select标签

select标签:发送select 语句

id属性:当前名称空间下的statement的唯一标识。必须。要求id和mapper接口中的方法的名字一致。

select 标签中  
resultType:将结果集映射为java的对象类型必须要有(和 resultMap 二选一)
resultType使用注意:select查询出来 列名要和resultType指定的类型属性名对应,否则完成不了映射赋值。如果列名与类的属性名不一致则需要用自定义resultMap,和列名不一样的属性名要用resultMap的子标签id和result设置property、colum。

parameterType:传入参数类型。可以省略,会自判断传入的是什么类型 

	
    

7.2、insert标签

id属性:当前名称空间下的statement的唯一标识(必须属性);
parameterType:传入的参数类型,可以省略。

    
    
        INSERT INTO tb_user (id, user_name, sex)
        VALUES (#{id}, #{userName}, #{sex})
    

7.3、update标签

id属性:当前名称空间下的statement的唯一标识(必须属性);
parameterType:传入的参数类型,可以省略

 
    
        UPDATE tb_user SET user_name = #{userName}, sex = #{sex} WHERE id = #{id};
    

7.4、delete标签

#{ 只是表示占位可以随便写 } 相当于 ? 前提一定是一个变量

  
    
        delete from tb_user where id = #{id}
    

你可能感兴趣的:(Mybatis,mybatis,java,spring)