1.开发数据持久层
该项目对于数据库的管理采用Mybatis3.5 + Alibaba Druid连接池的方式连接数据库,创建一份配置文件对数据库进行连接操作,连接方式使用JDBC。
创建数据库连接的配置文件的时候,产生两个问题?
- 1.配置文件创建在哪里?
- 2.配置文件怎么写?
- 3.怎么写代码连接数据库?
- 4.怎么使用Alibaba Druid连接池进行数据库的连接操作?
2.创建配置文件
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&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&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&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="initialSize" value="10"/>
<property name="maxActive" value="20"/>
</dataSource>