您的位置:首页 > 编程语言 > Java开发

工具类封装、DAO模式和自定义连接池(java)

2019-08-29 20:33 477 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/SjwFdb_1__1/article/details/100143034

1.工具类封装

工具类封装主要将对数据库的操作全部提取出来放在DbUtils工具类中,从而实现代码的复用。实现代码分层效果,提高代码逻辑结构。在需要修改模块功能是,只需将部分代码修改即可。

案例实现:实现对emp表的查询、添加、删除、修改

1.1将加载驱动类,获取连接对象的参数写入配置文件,用类加载器加载配置文件,通过IO流读写文件获取参数值

配置文件:db.properties

[code]driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myschool?useSSL=true&characterEncoding=utf8
username=root
password=root

1.2封装DbUtils工具类 封装对emp表的增删改查

重点:对数据库中数据的查询(利用反射和内省机制)

查询基本步骤描述:查询表格中所有记录

(1)获取连接对象conn,执行命令对象pstat

(2)pstat执行SQL语句,将结果集返回给结果集对象rs

(3)通过结果集对象拿到表格列名集(表头名集)

(4)遍历结果集,通过列名集拿到每行每列的对应的值value

(5)用泛型类对象创建对象T t=class1.newInstance(),并用列名和泛型类对象获取属性描述符(与实体类中的每个属性相对应)

(6)用属性描述符得到每个属性的setXXX()方法,调用反射方法invoke(t,value);给每个属性赋值

(7)最后将赋值的t对象添加到list集合中,完成读取数据库中的数据,遍历输出。

[code]public class DbUtils {
private static String driver;
private static String url;
private static String username;
private static String password;
static{
try {
Properties prop = new Properties();
InputStream is = DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
prop.load(is);
driver = prop.getProperty("driver");
url  = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");

Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
try {
return DriverManager.getConnection(url,username,password);
} catch (SQLException e) {
System.out.println("连接失败!");
e.printStackTrace();
}
return null;
}

public static void executeUpdate(String sql,Object...params){
Connection conn = DbUtils.getConnection();
if(conn!=null){
PreparedStatement pstat=null;
try {
pstat = conn.prepareStatement(sql);
if(params!=null){
for (int i = 0; i < params.length; i++) {
pstat.setObject(i+1,params[i]);
}
}
pstat.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
release(conn,pstat,null);
}
}
}

public static <T> List<T> findAll(String sql, Object[] params, Class<T> class1){
List<T> list = new ArrayList<>();
Connection conn=null;
PreparedStatement pstat=null;
ResultSet rs=null;
try {
conn = DriverManager.getConnection(url,username,password);
pstat = conn.prepareStatement(sql);
rs = pstat.executeQuery();
while(rs.next()){
try {
T t = class1.newInstance();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
//                    System.out.println(columnCount);
for (int i = 0; i < columnCount; i++) {
//得到每一列的列名
String columnLabel = metaData.getColumnLabel(i + 1);
//得到这一行列名对应的值
Object object = rs.getObject(columnLabel);
try {
//得到每一列的属性描述符
PropertyDescriptor pd = new PropertyDescriptor(columnLabel,class1);
if(pd!=null) {
//根据属性描述符得到其set方法
Method writeMethod = pd.getWriteMethod();
//把每一列的值赋给实体类对应的属性
writeMethod.invoke(t, object);
}
} catch (Exception e) {
//                            e.printStackTrace();
continue;
}
}
list.add(t);

} catch (Exception e) {
e.printStackTrace();
}
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
release(conn,pstat,rs);
}
return list;
}

public static <T> T findByEmpno(String sql,Class<T> class1,Object...params){
Connection conn=null;
PreparedStatement pstat=null;
ResultSet rs=null;
T t = null;
try {
conn = DriverManager.getConnection(url,username,password);
pstat = conn.prepareStatement(sql);
pstat.setObject(1,params[0]);
rs = pstat.executeQuery();
if(rs.next()){
try {
t=class1.newInstance();
ResultSetMetaData metaData = rs.getMetaData();
for (int i = 0; i < metaData.getColumnCount(); i++) {
String columnLabel = metaData.getColumnLabel(i + 1);
Object value = rs.getObject(columnLabel);

try {
PropertyDescriptor pd = new Propert
7ff7
yDescriptor(columnLabel,class1);
if(pd!=null){
Method writeMethod = pd.getWriteMethod();
writeMethod.invoke(t,value);
}

} catch (IntrospectionException e) {
//                            e.printStackTrace();
continue;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (SQLException e) {
e.printStackTrace();
}

return t;
}

public static void release(Connection conn, Statement stat, ResultSet rs){
try {
if(rs!=null){
rs.close();
}
if(stat!=null){
stat.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

以上封装好的工具类,配合DAO设计模式使用。

2.DAO设置模式

DAO(Database Access Object 数据库访问对象)

为了降低耦合性,提出了DAO封装数据库操作的设计模式。

它可以实现业务逻辑与数据库访问相分离。相对来说,数据库是比较稳定的,其中DAO组件依赖于数据库系统,提供数据库访问的接口,隔离了不同的数据库实现。

DAO模式的组成部分

1 DAO接口(主要包 添加 修改 查询 删除方法)

2 DAO实现类

3 实体类 (domain(领域)、beans、entity、pojo、model)

PO (VO)(Persistent Object, Value Object)

VO (View Object)

DTO (Data Transfer Object)

--作用:用在数据访问代码和业务逻辑代码之间通过实体类来传输数据

--实体类特征:

    ◦属性一般使用private修饰

    ◦提供public修饰的getter/setter方法

    ◦实体类提供无参构造方法,根据业务提供有参构造

    ◦实现java.io.Serializable接口,支持序列化机制

4 数据库连接和关闭工具类

设计的包名 :

domain 存放实体类

utils 存放工具类

dao 存放接口

dao.impl 存放实现类

DAO模式设计案例请参考https://blog.csdn.net/SjwFdb_1__1/article/details/100128177

3.自定义实现连接池

用户每次请求都需要向数据库获得连接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。

Java为连接池实现提供了一个规范(接口),规范的写法,我们需要实现DataSource接口!

案例如下:

注意:DataSource接口中有多个抽象方法,我们只需要实现getConnection方法,然后自己定义ralease()用于释放资源,把连接对象从新添加到连接池中。

[code]public class DbUtilsPool implements DataSource {

private static String driver;
private static String url;
private static String username;
private static String password;

private static List<Connection> connections = Collections.synchronizedList(new LinkedList<>());

static{
try {
Properties prop = new Properties();
InputStream is = DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
prop.load(is);
is.close();
driver = prop.getProperty("driver");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");

Class.forName(driver);
for (int i = 0; i < 5; i++) {
Connection conn = DriverManager.getConnection(url, username, password);
connections.add(conn);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//从连接池中取连接对象,存在返回连接对象,不存返回null
@Override
public Connection getConnection() throws SQLException {
return connections.remove(0);
}
//将连接对象放回连接池中
public static void release(Connection conn){
connections.add(conn);
}

@Override
public Connection getConnection(String s, String s1) throws SQLException {
return null;
}

@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}

@Override
public void setLogWriter(PrintWriter printWriter) throws SQLException {

}

@Override
public void setLoginTimeout(int i) throws SQLException {

}

@Override
public int getLoginTimeout() throws SQLException {
return 0;
}

@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}

@Override
public <T> T unwrap(Class<T> aClass) throws SQLException {
return null;
}

@Override
public boolean isWrapperFor(Class<?> aClass) throws SQLException {
return false;
}
}

测试代码:

[code]public class DbUtilsPoolTest {

@Test
public void testGetConn(){
for (int i = 0; i < 8; i++) {
DbUtilsPool myPool = new DbUtilsPool();
Connection conn = null;
try {
conn = myPool.getConnection();
System.out.println("连接"+conn.hashCode()+"成功!");
myPool.release(conn);
} catch (Exception e) {
System.out.println("连接超时,请重新连接......");
}
}
}
}

测试结果:

会产生重复连接对象,因为在连接池共产生5个连接对象,当我们需要的连接对象大于5个,就会产生重复连接对象。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: