Java Learning - 8. mybatis

目录

 Mybatis概述

IDEA配置Mybatis

编写程序

事务管理


         在项目开发中,需要进行Java与数据库的联动,然而编写JDBC相关语句实在是繁琐,极大地减缓了开发者的开发速率,因此需要一些框架的支持,来提供这个联动支持,Mybatis就是这样一种开发框架

 Mybatis概述

        Mybatis 是一款半自动ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低

        - ORM的意思是对象关系映射,可以在Java对象和数据库表的字段之间形成一种映射,使之能够联系起来,比如有一个Java的Book类,其中有booknum和bookname两个属性,又有一张数据表是book_info,其中有两个字段book_info_num和book_info_name,ORM可以提供booknum和book_info_num的映射关系,从而将这两个不同的软件内容联系起来,并且能够在此基础上进行增删查改操作

        - 半自动的意思是虽然能够提供映射关系,不用手撸JDBC的内容,但是还是需要开发者手写SQL语句,因此叫做半自动,也提供了很高的灵活性!

IDEA配置Mybatis

        1. 首先需要创建一个maven项目(更方便地管理这个项目的依赖等)

        2. 打开创建完的项目的pom.xml,在其中添加mybatis的jar包,具体信息可以在

       http:// https://mvnrepository.com/artifact/com.mysql/mysql-connector-j

        这个url中找到,这里我直接将其添加到依赖中

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        3. 新建一个xml文件名为mybatis-config.xml,这个文件用于配置该项目的mybatis特性

        在文件顶部写上相关的版本信息

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">

        这里可以使用file template,避免重复编写

        在configuration字段中添加environments,设置为mysql数据库类型,并且填入自己的事务管理以及数据库的连接与登录信息等,注意在url字段就是jdbc的填写方法,很简单

    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatisdemo?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="..."/>
            </dataSource>
        </environment>
    </environments>

        除了这种方法,还可以在mybatis-config中加入properties标签,将JDBC连接信息写在jdbc.properties文件中,直接用符号引用即可

         

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatisdemo?characterEncoding=utf-8
username=root
password=wujiayi0303
    <properties resource="jdbc.properties"></properties>

        除此之外,还需要加入一个映射关系map,这个具体在后面会讲到,这里只需要先知道这是一个映射关系,将Java的方法与对应的SQL语句相关联即可,也就是说,有了这张关系映射表之后,调用Java中的方法,会自动执行对应的SQL语句,这张表也需要创建,这里先空着

    <mappers>
        <mapper resource="mappers/StudentMapper.xml"></mapper>
    </mappers>

编写程序

        1. 在java文件夹下创建一个StudentDAO接口(dao)和一个Student类(pojo)

                

         2. 编写相关属性与方法

public interface StudentDAO {
    public int insertStudent(Student student);
}
public class Student {
    private int stuID;
    private String stuNum;
    private String stuName;
    private String stuGender;
    private String stuAge;
}

        3. 在StudentDAO接口中有一个插入学生的方法,那如何将这个方法实例化并且映射到响应的SQL语句呢,这就需要在之前创建的map.xml文件中进行配置了

        打开那个文件,在头部加上一些固定的东西

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

        添加<mapper></mapper>,其中namespace是映射到这个表的那个接口类的reference path

<mapper namespace="com.aki.dao.StudentDAO">
</mapper>

        然后就能够在其中添加这个StudentDAO接口类中的映射了,添加一个insert,内部编写SQL语句内容,要注意的是values中特别的语法 #{stuNum}

        - 这个#{stuNum}的意思是在Java方法的参数中,找到对应属性名的属性,并提取它的值

<insert id="insertStudent" parameterType="com.aki.pojo.Student" useGeneratedKeys="true" keyProperty="stuID">
    insert into tb_students(stunum,stuname,stugender,stuage)
    values(#{stuNum},#{stuName},#{stuGender},#{stuAge})
</insert>

        还有一个需要关注的点就是parameterType,这里指定了参数的类型是com.aki.pojo下的Student,实际上,如果在Java方法中参数已经规定了,这里可以省略

        另外,useGeneratedKeys意思是自动回填参数的键值,这个字段是后面keyProperty规定的

        此外,如果参数只有一个,实际上在配置文件中不管填什么名字,都会自动匹配到这个

        4. 编写测试类,对这个映射进行测试

       首先编写要给mybatis_utils,mybatis_utils.getSqlSession()实际上是我自定义的,用会话工厂来获取连接的,其中会话工厂建立在我的配置文件基础上,因此要先读取我的配置文件mybatis-config.xml,这里用ibatis提供的Resources中的getResourceAsStream就能获取

public class mybatis_utils {
    private  static SqlSessionFactory factory;
    private static final ThreadLocal<SqlSession> local=new ThreadLocal<>();

    static {
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        factory= sqlSessionFactoryBuilder.build(is);

    }

    public static SqlSession getSqlSession(){
        SqlSession sqlSession=local.get();
        if(sqlSession==null){
            sqlSession=factory.openSession();
            local.set(sqlSession);
        }
        return sqlSession;
    }
}

        写测试代码,利用SqlSession的getMapper函数实现一个接口类,并且测试其,注意这里要手动提交事务,因此加上sqlSession.commit()

    public void testinsertStudent() throws IOException {
        //is读取配置文件
        SqlSession sqlSession = mybatis_utils.getSqlSession();
        StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
        System.out.println(studentDAO);
        //使用DAO中的方法
        Student student  = new Student(0, "10005", "吴八", "男", "20");
        int i = studentDAO.insertStudent(student);
        System.out.println(i);
        System.out.println(student);
        //手动提交
        sqlSession.commit();

    }

          运行看看测试结果

        在数据库中这条数据也是成功添加进去了

         5. 这是简单的添加数据操作,如果需要查询数据,可能会遇到一些麻烦

        因为查询出的数据通常有多个字段,而在这种映射关系中,如果不去人为规定,机器很难去确定到底哪一个字段应该传到哪一个属性中,这就需要一个工具来提供这种传递的映射关系

        好在mybatis提供了一个叫resultMap的映射关系,能够将数据库中的字段与Java类中的属性关联起来!其中id是自定义的,type是规定这个映射到的Java类,column的内容是数据表中的字段,property中的内容是type这个Java类中的属性名

  <resultMap id="listStudents_2_map" type="com.aki.pojo.Student">
    <id column="sid" property="stuID"/>
    <id column="stunum" property="stuNum"/>
    <id column="stuname" property="stuName"/>
    <id column="stugender" property="stuGender"/>
    <id column="stuage" property="stuAge"/>
  </resultMap>

         随后,在编写select语句时,在resultMap属性中加入这个id就可以了!

  <select id="listStudents_2" resultMap="listStudents_2_map">
    select sid ,stunum ,stuname ,stugender ,stuage from tb_students
  </select>

        注意!因为查询动作常常会返回多条数据,因此在Java查询的方法的返回类型也要能够存放多个该类对象,故如下创建即可

    public List<Student> listStudents_2();

        在测试文件中编写测试方法

   @Test
    public void testlistStudents_2() throws IOException {
        SqlSession sqlSession = mybatis_utils.getSqlSession();
        StudentDAO studentDAO=sqlSession.getMapper(StudentDAO.class);

        List<Student> list =studentDAO.listStudents_2();
        for(Student stu:list){
            System.out.println(stu);
        }
        assertNotNull(list);
    }

        运行结果如下,返回了各个数据!

        

        值得一提的是,在查询数据时,其实不需要用到事务提交,只需要得到数据即可,因此可以在Mybatis_utils中封装getMapper的函数 

public static <T extends Object> T getMapper(Class<T> c){
        SqlSession sqlSession=getSqlSession();
        return sqlSession.getMapper(c);
}

         6. 到此为止,我们编写的方法都是一个参数的,如果需要两个参数呢?比如要查询stunum=10009和stuname=王五的数据,又该如何告知mapper哪个参数对应哪个呢

        这里就要用到Java提供的@Param了!

    public Student queryStudent(@Param("num") String num,@Param("name") String name);

        编写mapper

  <select id="queryStudent" resultMap="listStudents_2_map">
    select sid ,stunum ,stuname ,stugender ,stuage from tb_students where stunum=#{num} and stuname=#{name}
  </select>

        编写测试文件

    @Test
    public void testqueryStudent() throws IOException {
        SqlSession sqlSession = mybatis_utils.getSqlSession();
        StudentDAO studentDAO=sqlSession.getMapper(StudentDAO.class);

        Student s =studentDAO.queryStudent("10009","王五");
        System.out.println(s);
    }

        测试结果如下

        

        至此,mybatis入门结束!

事务管理

        在上面编写配置文件以及测试程序的过程中,其实已经提到了一些事务管理的方法,比如封装getSqlSession和getMapper的方法,这里会扩展更多

        1. 手动提交事务

        在之前的例子中,我们都是使用手动提交事务 SqlSession.commit(),每次都要写这一行代码显得很麻烦,有没有上面办法让它自动提交呢,答案是肯定的

        2. 自动提交事务

        在mybatis的openSession函数中,提供了一个可选参数,若openSession(true),则表示该session的事务是自动提交,无须手动添加(默认设置为false,需要手动commit())

        在封装中也可以加入参数,自行设置是否自动提交事务

    public static SqlSession getSqlSession(boolean isAutoCommit){
        SqlSession sqlSession=local.get();
        if(sqlSession==null){
            sqlSession=factory.openSession(isAutoCommit);
            local.set(sqlSession);
        }
        return sqlSession;
    }

        同样的,在getMapper中也可以设置自动提交事务,注意!这里直接设置为true是因为,如果要使用getMapper方法直接获取结果,意思就是不想手动管理事务,因此直接设置为true

public static <T extends Object> T getMapper(Class<T> c){
        SqlSession sqlSession=getSqlSession(true);
        return sqlSession.getMapper(c);
}

        值得一提的是,如果一个方法中有多个SQL操作,建议使用手动提交事务,并且catch异常,进行回滚(rollback)处理,因为如果有多个SQL操作1、2、3,设置为自动提交事务的情况下,操作1完成后直接提交,操作2完成后也直接提交,此时如果操作3产生异常,则只有操作3无法提交,但是没有回滚操作,因此建议只有一个SQL操作时才建议使用自动提交

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值