年轻人的第一个MyBatis项目就要这样来学习,不走弯路

248 阅读5分钟

之前在我自己的公众号:Java架构师联盟发布了一篇mybatis-plus的文章之后,有小粉丝跟我说,现在刚开始学习Java,是不是可以不用学mybatis了直接学这个啊,听得我心里一阵后怕,总感觉自己带偏了他们的想法

其实我个人觉得,这不仅仅是他这种初学者,也是很多人的错误想法,就是觉得新的技术就是好的,不信?看这个,这也是一个初学者,在写代码的过程中遇到这样一个问题

年轻人的第一个MyBatis项目就要这样来学习,不走弯路

原因,我直接上聊天记录吧

年轻人的第一个MyBatis项目就要这样来学习,不走弯路

怎么样,这个问题简单吗?但是也凸显了一个问题,学习,尤其是开发这一行,真的不能激进,所以我借着今天的这个引子,整理今天的这份文章--mybatis,从最一开始的mybatis入门直到整合spring,并且附代码实现,刚开始学习的朋友可以实际操作一下,老牌程序员可以回顾一下当年的青葱岁月,哈哈哈哈哈

我们来看今天的正题吧

MyBatis前世

原生JDBC操作数据库的流程

加载驱动

获取链接 connection

获取statement

设置sql

给占位符 set值

执行sql,获取结果集

对结果集进行解析、封装

释放资源

原生的jdbc操作数据库的缺点:

频繁地进行获取链接、关闭链接,资源浪费。 数据库连接池

sql语句属于硬编码,维护不方便。并且需求变得可能性大,要经常地修改sql

占位符设置参数也属于硬编码,维护不方便

结果集解析过程也是硬编码,希望是能够自动地封装成我们自己开发的pojo对象中去

mybatis入门

mybatis 是一个持久层框架 ORM,他可以对jdbc的操作过程进行封装,使开发者只需关注sql本身,而无需去处理 注册驱动、获取链接、获取statement、结果集解析、资源释放等工作。

ORM :Object Ralational Mapping 对象关系映射 简单地说,是通过描述对象和关系数据库之间的元数据的映射关系,将java中的对象持久化到关系数据库中。

mybatis配置

1、全局配置文件mybatis.xml(名字任意) 配置mybatis的运行环境,包括连接池、事务等。

2、配置映射文件(配置sql)mapper.xml

3、SqlSessionFactory(会话工厂,通过配置文件获取的) 创建SqlSession。

4、SqlSession(会话) 操作数据库。

5、Executor(执行器) sqlSession是通过执行器来操作数据库的。

6、mapped Statement(底层封装对象) 对数据库的操作进行封装,包括sql、输入参数、输出结果。

支持的输入输出参数类型

java基本类型

hashmap

自定义pojo对象


简单的Mybatis入门程序

项目架构

年轻人的第一个MyBatis项目就要这样来学习,不走弯路

jar包

年轻人的第一个MyBatis项目就要这样来学习,不走弯路

log4j.properties

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

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>
    <!--mybatis的运行环境
        mybatis与Spring整合后就不需要了
    -->
    <environments default="sqlServer">
        <environment id="sqlServer">
           <!-- 事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据库连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"></property>
                <property name="url" value="jdbc:sqlserver://localhost:1433;database=ssm"></property>
                <property name="username" value="sa"></property>
                <property name="password" value="123456"></property>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="UsersMapper.xml"></mapper>
    </mappers>
</configuration>

Users.java

public class Users {
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

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

Users.mapper

<?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;命名空间
    作用:分割sql
    -->
<mapper namespace="UserMapper">
    <!--根据姓名查询用户信息-->
    <!--
        id用于标识映射文件中的sql,其实是statement的id
        parameterType:参数类型
        resultType:输出结果类型,单条结果的类型
        #{}:占位符。如果为简单类型,则可以通过#{value}来取值,也可以通过#{任意名字}来取值
    -->
    <select id="selectById" parameterType="int" resultType="com.me.pojo.Users">
        select * from users where id=#{id}
    </select>

    <!--${}字符串拼接,不能防止sql注入-->
    <select id="selectByUserName" parameterType="String" resultType="com.me.pojo.Users">
        /*传参为‘李%’*/
        select * from users where username like #{value}
        /*传参为‘李’*/
        /*select * from users where username like '${value}%'*/
    </select>
</mapper>

UsersTest.java

package com.me.test;

import com.me.pojo.Users;
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.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UsersTest {
    private SqlSessionFactory sqlSessionFactory;
    @Before
    public void init() throws IOException {
        //获取全局配置文件
        InputStream in= Resources.getResourceAsStream("mybatis.xml");
        //获取SqlSessionFactory
        sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
    }

    @Test
    public void test() throws IOException {


        //获取sqlSession
        SqlSession sqlSession=sqlSessionFactory.openSession();
        //执行sql
        Users user=sqlSession.selectOne("UsersMapper.selectById",1);
        System.err.println(user.getUsername());
        sqlSession.close();
    }

    @Test
    public void test2(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        List<Users> usersList=sqlSession.selectList("UsersMapper.selectByUserName","李%");
        /*List<Users> usersList=sqlSession.selectList("UsersMapper.selectByUserName","李");*/
        System.err.println(usersList);
        /*System.out.println(usersList.get(0).getUsername());
        System.out.println(usersList.get(1).getUsername());*/
    }
}

mybatis对数据库的常用操作

一、查询

    <select id="selectById" parameterType="int" resultType="com.me.pojo.Users">
        select * from users where id=#{id}
    </select>

    <!--${}字符串拼接,不能防止sql注入-->
    <select id="selectByUserName" parameterType="String" resultType="com.me.pojo.Users">
        /*传参为‘李%’*/
        select * from users where username like #{value}
        /*传参为‘李’*/
        /*select * from users where username like '${value}%'*/
    </select>

测试方法

    @Test
    public void selectByUserName(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        List<Users> usersList=sqlSession.selectList("UsersMapper.selectByUserName","李%");
        /*List<Users> usersList=sqlSession.selectList("UsersMapper.selectByUserName","李");*/
        System.err.println(usersList);
        /*System.out.println(usersList.get(0).getUsername());
        System.out.println(usersList.get(1).getUsername());*/
    }

二、新增

<!--添加用户信息-->
    <insert id="addUser" parameterType="com.me.pojo.Users">
        insert into users(id,username,password,address,birthday,sex) values(#{id},#{username},
        # {password},#{address},#{birthday},#{sex})
    </insert>

    <insert id="addUser2" parameterType="com.me.pojo.Users" keyProperty="id" useGeneratedKeys="true">
        insert into users(id,username,password,address,birthday,sex) values(#{id},#{username},# 
        {password},#{address},#{birthday},#{sex})
    </insert>

测试方法

    @Test
    public void addUser(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        Users users=new Users(4,"王五","123",new Date(),"男","北京");
        int res=sqlSession.insert("UsersMapper.addUser",users);
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void addUser2(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        Users user=new Users(5,"王五","123",new Date(),"男","北京");
        int res=sqlSession.insert("UsersMapper.addUser",user);
        System.err.println("res:"+res);
        System.err.println("users.getId:"+user.getId());
        sqlSession.commit();
        sqlSession.close();
    }

三、修改

    <update id="updateUser" parameterType="com.me.pojo.Users">
        update users set password=#{password},address=#{address} where id=#{id}
    </update>

测试方法

    @Test
    public void updateUser(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        Users user=new Users();
        user.setPassword("newPass123456");
        user.setAddress("济南");
        user.setId(4);
        int res=sqlSession.update("UsersMapper.updateUser",user);
        sqlSession.commit();
        sqlSession.close();
    }

四、删除

    <delete id="deleteUser" parameterType="int">
        /*这里是简单类型,# { value } 中的value可以任意写*/
        delete from users where id=#{id}
    </delete>

测试方法

    @Test
    public void deleteUser(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        int res=sqlSession.delete("UsersMapper.deleteUser",5);
        System.err.println("res:"+res);
        sqlSession.commit();
        sqlSession.close();
    }

mybatis.xml的一些配置项

1、加载外部资源文件

<properties resource="db.properties"></properties>

2、起别名

    <typeAliases>
        <!--
            起别名第一种方式
            type:给哪个类起别名 alias:别名
        -->
        <!--<typeAlias type="com.me.pojo.Users" alias="user"></typeAlias>-->

        <!--
            起别名第二种方式:批量起别名
            name:包,起的别名就是类名的全名,首字母大写、小写皆可
        -->
        <package name="com.me.pojo" />
    </typeAliases>

3、SqlSessionFactory和SqlSession

    //获取全局配置文件
    InputStream in= Resources.getResourceAsStream("mybatis.xml");
    //获取SqlSessionFactory
    sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
    //获取sqlSession
    qlSession sqlSession=sqlSessionFactory.openSession();
    //执行sql

SqlSessionFactory:它是通过全局配置文件获取的,SqlSessionFactoryBuilder创建的。一旦它被创建,就会在程序的执行期一直存在,因此只需要一个实例。也就是说希望它是单例的。 SqlSession:作用是操作数据库,是线程不安全的。因而希望每个线程都有自己的sqlSession的实例。

4、工具类

package com.me.utils;

import org.apache.ibatis.io.Resources;
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;

    static{
        try {
            //获取全局配置文件
            InputStream in= Resources.getResourceAsStream("mybatis.xml");
            //获取SqlSessionFactory
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSessionFactory getSqlSessionFactory(){
        return sqlSessionFactory;
    }
}

5、测试类

    @Test
    public void selectById() throws IOException {
        //获取sqlSession
        SqlSession sqlSession= MybatisUtils.getSqlSessionFactory().openSession();
        //执行sql
        Users user=sqlSession.selectOne("UsersMapper.selectById",1);
        System.err.println(user.getUsername());
        sqlSession.close();
    }

Spring与Mybatis整合

mybatis:dao层,操作数据库,需要单例的SqlSessionFactory工厂。 spring:容器,管理对象。 可以将SqlSessionFactory、事务、连接池以及mapper的动态代理交给spring来做。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/spring-aop.xsd">

    <!--加载外部资源文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--数据库连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--配置SqlSessionFactory,通过Spring来管理会话工厂-->
    <bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源:因为要使用SqlSession操作数据库-->
        <property name="dataSource" ref="dataSource"></property>
        <!--加载mybatis的全局配置文件-->
        <!--<property name="configLocation" value="classpath:mybatis.xml"></property>-->
        <!--Spring起别名-->
        <property name="typeAliasesPackage" value="com.me.pojo"></property>
    </bean>

    <!--mapper动态代理 通过扫描批量加载mapper接口来创建代理bean,这些bean的名字是接口名字(首字母小写)-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--指定mapper接口的包路径-->
        <property name="basePackage" value="com.me.mapper"/>
    </bean>

    <!--注解扫描-->
    <context:component-scan base-package="com.me.service"></context:component-scan>
</beans>

UsersService.java

public interface UsersService {
    public Users selectById(int id);
}

UsersServiceImpl

@Service("userService")
public class UsersServiceImpl implements UsersService {

    @Autowired
    private UsersMapper usersMapper;

    @Override
    public Users selectById(int id) {
        return usersMapper.selectById(id);
    }
}

测试类

public class AppTest {
    @Test
    public void selectById(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        UsersService usersService= (UsersService) applicationContext.getBean("userService");
        Users user=usersService.selectById(1);
        System.err.println(user.getUsername());
    }
}

总结

好了,不知道看完今天的内容大家感觉怎么样,有没有收获,我基本是按照从入门开始,逐步的往里面填充一些知识的顺序将mybatis进行了整理,那这个时候,我想,在实际的学习过程中你肯定还会遇到一些这样那样的问题,但是千万不要突进,脚踏实地,就从一些基础的,无聊的东西开始一点点的学习,网络上那些说这个牛,哪个好的,他肯定有一门傍身的技术作为基础,所以才能打到他说的那个层次

最后,所有程序员都能当架构师,哈哈哈哈哈