欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis连接数据库的详细操作

程序员文章站 2022-05-03 10:23:23
...

最近学习一下Maven的使用,发现是真的香,然后顺带就学到了SSM这个熟悉的身影中的MyBatis这个持久层框架。这是我第一次使用框架来学习java,感觉难度瞬间就上去了,别说懂原理,就是基本使用都花了好几天反复看教程才调试通,留下了菜鸡的泪水QAQ。。不过有一说一,框架确实方便了开发,废话不多说,看看具体的流程吧

一、Mybatis连接数据库

1、简单连接的流程

- 连接数据库,导入jar包依赖(pom.xml)

这里用Maven来部署文件

<!--pom.xml中导入依赖-->
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

这里是在核心配置文件的设置,完整代码在后面有

<!--property属性可以通过外部properties文件导入-->
<properties resource="db.properties" />

<!--mybatis.xml中配置数据库信息-->
<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

这里的JDBC连接操作应该都很熟了

#db.properties
#url配置时区和字符集
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/xx?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
username=xxx
password=xxxx

- 建造工具类(MybatisUtils.java)

//MyBatis官方给出的代码
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =  new SqlSessionFactoryBuilder().build(inputStream);
/**
* 工具类
* SQLSession的创建写在静态代码块里
* 程序执行时就创建出来一个SqlSession对象
*/
public class MybatisUtils {

    private  static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回一个SQLSession(建议还是不要自动提交,防止出错也保存到数据库中)
     * @return 设置true,自动提交
     */
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);
    }

}

- 编写核心配置文件(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>
    <!--导入外部属性文件-->
    <properties resource="db.properties" />
   
<!--
	建立连接
	这里的default属性是为了适配不同环境,使用不同的数据库连接(如测试环境、发布环境等)
	default在id中取值
	事务处理方式(transactionManager):JDBC事务处理模式(commit,rollback,close)
	连接类型(dataSource):POOLED,连接池模式(连接可回收,用完了放回池子里)
-->
    <environments default="development">
        
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
        
        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

<!--配置映射Mapper,只有配置了 mappers 信息后,MyBatis才知道去哪里加载 Mapper映射文件-->
    <mappers>
        <mapper resource="com/qs/map/StudentMapper.xml"/>
    </mappers>

</configuration>

- 编写实体类(Student.java)

这里就不写代码了,无非就是构造方法和getter和setter方法

- 编写接口(StudentMapper.java)

public interface StudentMapper {
    List<Student> getStudentList();

    /**
     * 注解实现CRUD
     * 方法有多个参数,要在参数前加上@Param注解
     */
    @Select("select * from student where id = #{id}")
    Student getStudentById(@Param("id") int id);

    int addStudent(Student student);

    int updateStudent(Student student);

    int deleteStudent(int id);
}

- 和接口在同一目录下编写Mapper映射配置文件(StudentMapper.xml)

​ namespace、id、resultType等的配置

​ 然后不同语句在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">

<mapper namespace="com.qs.map.StudentMapper">

    <!--设置resultMap来映射实体类到数据库的字段-->
    <resultMap id="StudentMap" type="Student">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="email" property="email"/>
        <result column="age" property="age"/>
    </resultMap>

    
    <!--下面执行SQL语句-->
    <select id="getStudentList" resultType="student" resultMap="StudentMap">
        select * from student
    </select>

<!--
    前面用了注解的方式来完成SQL语句,这里就不用写了
    <select id="getStudentById" parameterType="int" resultType="student">
        select * from student where id = #{id}
    </select>
-->

    <insert id="addStudent" parameterType="student">
        insert into student (id,name,email,age) values (#{id},#{name},#{email},#{age})
    </insert>

    <update id="updateStudent" parameterType="student" >
        update student set name=#{name},email=#{email},age=#{age}  where id = #{id}
    </update>
    
    <delete id="deleteStudent" parameterType="int">
        delete from student where id = #{id}
    </delete>
</mapper>

- 编写测试文件实现接口的方法(可使用@Test注解来测试Mapper接口的方法)

//使用@Test注解要在pom.xml中添加junit依赖
//用@Test注解可以不用main方法也可以执行
public class StudentMapperTest {
    @Test
   public void test() {
        SqlSession sqlSession=null;
        try {
            sqlSession = MybatisUtils.getSqlSession();
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            List<Student> studentList = studentMapper.getStudentList();
            for (Student stu : studentList) {
                System.out.println(stu);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    @Test
    public void getStudentById() {
        SqlSession sqlSession=null;
        try {
            sqlSession = MybatisUtils.getSqlSession();
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

            Student student = studentMapper.getStudentById(2);
            System.out.println(student);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    @Test
    public void addStudent(){
        SqlSession sqlSession = null;

        try {
            sqlSession = MybatisUtils.getSqlSession();
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            int result = studentMapper.addStudent(new Student(4,"哈哈","aaa@qq.com",22));

            if (result>0) {
                System.out.println("添加成功!");
            }

		//增删改操作一定要提交事务
            sqlSession.commit();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    @Test
    public void updateStudent() {
        SqlSession sqlSession = null;

        try {
            sqlSession = MybatisUtils.getSqlSession();
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            int result = studentMapper.updateStudent(new Student(4,"嘿嘿","121212",18));

            if (result>0) {
                System.out.println("修改成功!");
            }

		//增删改操作一定要提交事务
            sqlSession.commit();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    @Test
    public void deleteStudent() {
        SqlSession sqlSession = null;

        try {
            sqlSession = MybatisUtils.getSqlSession();
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            int result = studentMapper.deleteStudent(4);

            if (result == 1) {
                System.out.println("删除成功!");
            }
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            assert sqlSession != null;
            sqlSession.close();
        }
    }
}

- 修改pom.xml,设置资源过滤器(防止Maven导出资源失败)(可选)

	<build>
    	<resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

2、常见问题(各种bug)

这些问题忘了把具体的问题保存下来了,只记得找到的一些解决办法,后面再遇到再完善

  • 配置文件没有注册、绑定接口错误

    (多半是映射配置文件名错了)检查核心配置文件中是否配置mapper映射)

    配置文件中的mapper标签一定要仔细观察,很多时候错误都是mapper没有配置好

  • 方法名不对

  • 返回类型不对

  • Maven导出资源问题(设置资源过滤器)

二、Mybatis三个核心接口(使用不当会造成并发问题)

1、SqlSessionFactoryBuilder(局部作用域)

​ 用来创建多个SQLSessionFactory实例,一旦创建,SQLSessionFactoryBuilder就丢弃了

2、SqlSessionFactory(应用作用域)

​ 简单说就是数据库连接池,被创建出来就一直存在可以使用
​ 建议不要重复创建,会造成资源浪费

3、SqlSession(对象)

​ 线程不安全,最好放在一个方法中
​ 每次收到的HTTP请求,就可以打开一个SQLSession,
​ 返回一个响应,就可以关闭它(关闭放在finally中执行)
​ 每个SQLSession可以对应多个Mapper,每个Mapper对应一个业务MyBatis连接数据库的详细操作

三、一些操作

1、CRUD操作(增删查改)

​ 1、namespace
​ 包名要和Mapper接口的包名一致
​ 2、select
​ id:就是对应的namespace中接口的方法名

​ …

2、给实体类起别名(typeAliases)

​ 方式一:(这种方式的别名是自定义的)

    <typeAliases>
            <typeAlias type="全类名" alias="别名"/>
    </typeAliases>

​ 方式二:(这种方式的别名是类名,建议首字母小写,但是可以用注解起别名)

    <typeAliases>
            <package name="包名"/>
    </typeAliases>

3、映射器常见配置(mapper)

数据库配置文件外部引入实体类别名

保证Mapper接口和Mapper.xml名字一致,并且在同一个包下

4、解决属性名和字段名不一致的问题

​ 暴力解决(SQL起别名
​ resultMap(结果集映射

四、日志

1、常见的工具

​ log4j
​ stdout_logging

2、核心配置文件中设置日志

<!--如果是log4j,则需要导入log4j的jar包,并配置一个log的属性文件-->
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

数据库配置文件外部引入实体类别名

保证Mapper接口和Mapper.xml名字一致,并且在同一个包下

4、解决属性名和字段名不一致的问题

​ 暴力解决(SQL起别名
​ resultMap(结果集映射

四、日志

1、常见的工具

​ log4j
​ stdout_logging

2、核心配置文件中设置日志

<!--如果是log4j,则需要导入log4j的jar包,并配置一个log的属性文件-->
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>