Java项目-OA办公系统2

101 阅读3分钟

1.开发数据持久层

  该项目对于数据库的管理采用Mybatis3.5 + Alibaba Druid连接池的方式连接数据库,创建一份配置文件对数据库进行连接操作,连接方式使用JDBC。
  创建数据库连接的配置文件的时候,产生两个问题?

  • 1.配置文件创建在哪里?
  • 2.配置文件怎么写?
  • 3.怎么写代码连接数据库?
  • 4.怎么使用Alibaba Druid连接池进行数据库的连接操作?

2.创建配置文件

image.png

在maven工程下,存在一个**resources**目录,在该目录下创建**mybatis-config.xml**配置文件。

3.配置文件怎么写

  需要注意的是下面这份配置文件是采用Alibaba Druid的方式进行配置的,所以连接源是com.oa.datasource.DruidDataSourceFactory;并且连接的property可能和原Mybatis的property有所不同
  第二个需要注意的是,对于驼峰命名转换进行配置,比如说数据库中的字段信息是user_id,那么在Servlet中存在的属性字段信息是userId,如果不开启驼峰命名转换操作,从数据库中读取字段数据user_id无法和userId进行匹配操作。

<?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>
    <settings>
        <!--开启驼峰命名转换 form_id->formId-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <!-- <dataSource type="POOLED"> -->
            <dataSource type="com.oa.datasource.DruidDataSourceFactory">
                <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://localhost:3306/oa?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
                <property name="initialSize" value="10"/>
                <property name="maxActive" value="20"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

4. 通过读取配置文件连接数据库

废话不多说先上代码!代码分为两部分。

  • 通过mybatis-config.xml配置文件连接数据库——MybatisUtils类的实现
  • 通过Alibaba Druid实现连接池——DruidDataSourceFactory

第一部分:MybatisUtils类的实现

package com.oa.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.Reader;
import java.util.function.Function;

public class MybatisUtils {
    // 利用static(静态)属于类不属于对象,且全局唯一
    private static SqlSessionFactory sqlSessionFactory = null;

    // 利用静态块在初始化类时进行实例化sqlSessionFactory
    static {
        Reader reader = null;
        try {
            // 读取mybatis-config.xml
            reader = Resources.getResourceAsReader("mybatis-config.xml");
            // 构建SqlSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            // 初始化错误时,通过抛出异常ExceptionInInitializerError通知调用错误
            throw new ExceptionInInitializerError(e);
        }
    }

    // 函数式接口在开发中的使用操作
    // 使用函数式接口的方式进行数据操作
    public static Object executeQuery(Function<SqlSession, Object> func) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            Object obj = func.apply(sqlSession);
            return obj;
        } finally {
            sqlSession.close();
        }
    }

    public static Object executeUpdate(Function<SqlSession, Object> func) {
        SqlSession sqlSession = sqlSessionFactory.openSession(false);
        try{
            Object obj = func.apply(sqlSession);
            sqlSession.commit();
            return obj;
        }catch (Exception e) {
            sqlSession.rollback();
            throw e;
        }finally {
            sqlSession.close();
        }
    }

// 以下这种方法可以进行也可以进行开启和关闭操作
// 但是,如果程序员在使用的时候,忘记使用关闭方法,那么数据库连接操作马上就会占满了,数据库连接溢出
//    public static SqlSession openSession() {
//        return sqlSessionFactory.openSession();
//    }
//    public static void closeSession(SqlSession session) {
//        if (session != null) {
//            session.close();
//        }
//    }

}

  先对MybatisUtils进行说明,首先Mybatis的配置文件加载一次即可,所以想到使用静态代码块儿的概念,将读取配置文件和构建SqlSessionFactory对象全部都写到了static中,并在全局声明了静态类SqlSessionFactory,故在整个过程中SqlSessionFactory仅此一份。并且在抛异常时抛出ExceptionInInitializerError初始化异常。为什么要使用try..catch..finally这种方式进行书写操作呢?重点在finally中,不管上面代码是否存在异常,数据库连接必须关闭,如果采用以上注释代码的关闭方式,在使用该类时很可能就忘记关闭数据库,从而导致数据库连接断开,造成不必要的异常。还有一个需要注意的地方就是对于函数式编程的使用,这里我总结3个常用的函数式编程的类,如下图以便参考,中心思想就是加强函数的复用性,把函数看成一份资源。

JDK8常用函数式接口
接口用途
Consumer< T >对应有一个输入参数无输出的功能代码
Function<T, R>对应有一个输入参数且需要返回数据的功能代码
Predicate< T >用于条件判断,固定返回布尔值
import java.util.Random;
import java.util.function.Function;

public class FunctionSample {
    // 利用函数式接口生成定长随机字符串
    public static void main(String[] args) {
        Function<Integer, String> randomStringFunction = l -> {
            String chars = "abcdefghigklmnopqrstuvwxyz";
            StringBuffer stringBuffer = new StringBuffer();
            Random random = new Random();
            for(int i=0; i<chars.length(); i++) {
                int position = random.nextInt(chars.length());
                stringBuffer.append(chars.charAt(position));
            }
            return stringBuffer.toString();
        };

        // apply()方法进行调用
        String randomString = randomStringFunction.apply(32);
        System.out.println(randomString);
    }
}

以上举例子方便更好的对代码进行理解。

第二部分:Alibaba Druid实现连接池

package com.oa.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import javax.sql.DataSource;
import java.sql.SQLException;

public class DruidDataSourceFactory extends UnpooledDataSourceFactory {

    public DruidDataSourceFactory() {
        this.dataSource = new DruidDataSource();
    }

    @Override
    public DataSource getDataSource() {
        try {
            ((DruidDataSource)this.dataSource).init();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
        return this.dataSource;
    }
}

创建该类后,还需要在Mybatis的配置文件中进行修改,已在“3.配置文件怎么写”中进行修改:

<dataSource type="com.oa.datasource.DruidDataSourceFactory"> 
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> 
        <property name="url" value="jdbc:mysql://localhost:3306/oa?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true"/>
        <property name="username" value="root"/> 
        <property name="password" value="root"/> 
        <property name="initialSize" value="10"/> 
        <property name="maxActive" value="20"/> 
 </dataSource>