单例模式应用之---数据库连接

单例模式意图是
一个类只含有一个实例,并且只提供一个访问它的全局访问点。
我们在连接数据库时,需要创建数据库连接,而数据库的Connection是非常珍贵的资源,必须要重用,这时,我们可以用单例模式来创建Connection。
以下例子以mysql数据库连接举例。
首先,为了更方便的修改读取数据库的配置信息,我们将连接数据库时使用的驱动,数据库的用户名及密码、url地址存放于一个properties文件中(名称为db.properties)。

db.url=jdbc:mysql://localhost:3306/aa?useSSL=false&serverTimezone=UTC
db.user=root
db.password=123456
db.driver=com.mysql.cj.jdbc.Driver

建一个单例类Dbinfo 用于读取db.properties配置文件的信息,内容如下:

package com.icss.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

public class Dbinfo {
	private static Dbinfo dbinfo;//唯一的对象
	private  String url;
	private  String username;
	private  String password;
	private  String driver;
	public String getUrl() {
		return url;
	}
	public String getUsername() {
		return username;
	}	
	public String getPassword() {
		return password;
	}
	public String getDriver() {
		return driver;
	}

	//构造函数私有化
	private Dbinfo() {
		String fname = Dbinfo.class.getResource("/").getPath() + "/db.properties";
		InputStream in = null;
		try {
			in =  new FileInputStream(new File(fname));
			Properties pro = new Properties();//Properties类表示一组持久的属性。 Properties可以保存到流中或从流中加载。 属性列表中的每个键及其对应的值都是一个字符串。 
			pro.load(in);//从输入字节流读取属性列表(键和元素对)。
			//读取db.properties文件中的内容复制给当前唯一对象的属性
			this.url = pro.getProperty("db.url");
			this.password = pro.getProperty("db.password");			
			this.username = pro.getProperty("db.user");
			this.driver = pro.getProperty("db.driver");
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();	//关闭
				} catch (Exception e2) {
				}			
			}
		}		
	}
	//唯一的一个对象
	static {
		dbinfo = new Dbinfo();
		
	}
	
	public static Dbinfo instance() {
		return dbinfo;
	}
}

在dao层连接数据库时直接调用Dbinfo 类的instance()函数,并获取连接

package com.icss.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import com.icss.util.Dbinfo2;

public class BaseDao {
	
	protected Connection conn;
	public Connection getConn() {
		return conn;
	}
	public void setConn(Connection conn) {
		this.conn = conn;
	}


	public void openConnection() throws ClassNotFoundException,SQLException {	
		//conn必须可以多次重用
		if(this.conn == null || this.conn.isClosed() ) {
			//加载mysql的数据库驱动   包名+类名
	    	Class.forName(Dbinfo.getDriver());     	
	    	conn = DriverManager.getConnection(Dbinfo.getUrl(), Dbinfo.getUsername(), Dbinfo.getPassword());	
		}		
	}
	
	
	public void closeConnection() {
		if(conn != null) {
			try {
				conn.close();
			} catch (Exception e) {
				e.printStackTrace();		
			}			
		}
	}

package com.icss.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import com.icss.dto.UserStu;
import com.icss.entity.User;
import com.icss.util.Log;

public class UserDao extends BaseDao{
	 public User login3(String uname,String pwd) throws Exception {
	    	Log.logger.info("userdao:" + uname + "," + pwd);
	    	User user  = null;
	    	
	    	this.openConnection();
	    	String sql = "select * from tuser where uname=? and pwd=?";
	    	PreparedStatement ps = this.conn.prepareStatement(sql);
	    	ps.setString(1, uname);
	    	ps.setString(2, pwd);
	    	ResultSet rs = ps.executeQuery();
	    	while(rs.next()) {
	    		int role = rs.getInt("role"); 
	    		user = new User();
	    		user.setUname(uname);
	    		user.setPwd(pwd);
	    		user.setRole(role);
	    		break;
	    	}
	    	rs.close();
	    	ps.close();    	
			
			return user;
	 }
}


这样就实现了数据库连接的单例模式,以下为余下代码示例:
逻辑层(biz)

package com.icss.biz;

import com.icss.dao.UserDao;
import com.icss.dto.UserStu;
import com.icss.entity.User;

public class UserBiz {
	public User login3(String uname,String pwd) throws Exception{
		User user = null;
		UserDao dao = new UserDao();
		try {
			user = dao.login3(uname, pwd);	
		} catch (Exception e) {
			//异常处理后,二次抛出异常
			throw e;
		}finally {
			//关闭数据库链接
			dao.closeConnection();
		}
		return user;
	}

实体类(entity):

package com.icss.entity;

public class User {
	private String uname;
	private String pwd;
	private int role;
	
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public int getRole() {
		return role;
	}
	public void setRole(int role) {
		this.role = role;
	}
}

测试(ui):

package com.icss.ui;

import com.icss.biz.UserBiz;
import com.icss.dto.UserStu;
import com.icss.entity.IRole;
import com.icss.util.Log;

public class TestLogin {
	/**
	 * UI层必须捕获并处理异常
	 * @param uname
	 * @param pwd
	 */
	public static void login(String uname,String pwd) {
		UserBiz biz = new UserBiz();
		
		try {
			UserStu user = biz.login3(uname, pwd);
			if(user == null) {
				System.out.println(uname + ",登陆失败,用户名或密码错误");
			}else {
				System.out.println(uname + ",登陆成功,他是" + user.getName() );
				if(user.getRole() == IRole.ADMIN) {
					System.out.println(uname + "是管理员");
				}else if(user.getRole() == IRole.COMMON_USER) {
					System.out.println(uname + "是普通用户");
				}else if(user.getRole() == IRole.VIP_USER) {
					System.out.println(uname + "是VIP");
				}else {
					System.out.println(uname + " 身份信息不明");
				}
			}
		} catch (Exception e) {
			//异常记录日志,提示用户友好信息
			Log.logger.error(e.getMessage(),e);
			System.out.println("网络链接繁忙,请稍后再试");			
		}	
	}
	
	public static void main(String[] args) {
		TestLogin.login("16970744526", "123456");
	}

}

这样,单例模式,就成功的应用于数据库连接了。

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值