在我们写程序的时候,我们想要的代码就是高内聚低耦合,能重用,能按照需求能灵活改变,而在jdbc 这里我们我们变得就只有数据库了,所以在写代码的时候我们要注意些的代码在数据库边的时候是否能灵活的改变,废话少说下面我们就来看看使用工厂模式来封装的jdbc代码。
一、方式一代码如下:
1、数据库信息配置文件:ConnectionConfig.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/music?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
user=root
password=admin
2、配置文件读取代码:ConnectionConfig.java
package jdbc;
import java.io.IOException;
import java.util.Properties;
/**
* @author WHD data 2016年2月16日
*/
public class ConnectionConfig {
private static Properties prop = new Properties();
static {
try {
// InputStream input =
// ClassLoader.getSystemResourceAsStream("ConnectionConfig.properties");
// InputStream input =
// ConnectionConfig.class.getClassLoader().getSystemResourceAsStream("ConnectionConfig.properties");
// prop.load(input);
prop.load(ConnectionConfig.class.getClassLoader()
.getResourceAsStream("ConnectionConfig.properties"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String driver = prop.getProperty("driver");
public static String url = prop.getProperty("url");
public static String user = prop.getProperty("user");
public static String password = prop.getProperty("password");
}
3、获取Connection 接口代码:IDBConnection.java
package jdbc;
import java.sql.Connection;
/**
* @author WHD data 2016年2月15日
*/
public interface IDBConnection {
public abstract Connection getConnection();
public abstract void closeConnection(Connection conn);
}
4、获取Conection接口实现抽象类代码:AbstractConnectionImpl.java
package jdbc;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @author WHD data 2016年2月15日
*/
public abstract class AbstractConnectionImpl implements IDBConnection {
public void closeConnection(Connection conn) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Connection getConnection() {
// TODO Auto-generated method stub
return null;
}
}
5、获取Connection抽象类继承类代码:ConnectionImpl.java
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* @author WHD data 2016年2月16日
*/
public class ConnectionImpl extends AbstractConnectionImpl {
@Override
public Connection getConnection() {
// TODO Auto-generated method stub
Connection conn = null;
try {
Class.forName(ConnectionConfig.driver);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn = DriverManager.getConnection(ConnectionConfig.url,
ConnectionConfig.user, ConnectionConfig.password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
@Override
public void closeConnection(Connection conn) {
// TODO Auto-generated method stub
super.closeConnection(conn);
}
public static void main(String[] args) {
ConnectionImpl imp = new ConnectionImpl();
imp.getConnection();
}
}
6、获取IDBConnection实例其实也就是获取Connection实例的工厂类代码:DBConnectionFactory.java
package jdbc;
/**
*@author WHD
*data 2016年2月15日
*/
public class DBConnectionFactory {
//定义一个接口
private static IDBConnection instance;
//同步锁
private static Object initLock = new Object();
public static IDBConnection getInstance() {
if (instance == null) {
synchronized (initLock) {
instance=new ConnectionImpl();
}
}
return instance;
}
}
7、调用工厂类获取数据库链接代码:DBConnection.java
package jdbc;
import java.sql.Connection;
/**
* @author WHD data 2016年2月15日
*/
public class DBConnection {
public static Connection getConnection() {
/**
* 用户无需了解底层是如何实现的,它也不需要关心使用的是哪种数据库
*/
IDBConnection service = DBConnectionFactory.getInstance();
Connection conn = service.getConnection();
return conn;
}
public static void closeConnection(Connection conn) {
IDBConnection service = DBConnectionFactory.getInstance();
service.closeConnection(conn);
}
}
8、测试类代码:Test.java
package jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author WHD data 2016年2月15日
*/
public class Test {
public Test() {
}
public static void main(String[] args) throws SQLException {
Connection con = DBConnection.getConnection();
String sql = "select * from musics limit 10";
PreparedStatement pre = con.prepareStatement(sql);
ResultSet res = pre.executeQuery();
try {
while (res.next()) {
int id = res.getInt(1);
String title = res.getString(2);
System.out.println("id " + id + " title " + title);
}
} finally {
DBConnection.closeConnection(con);
}
}
}
9、代码执行结果
到这里我们的代码展示都结束了,我们来个小小的总结:
这个过程是 配置文件来配置数据库的相关信息,而ConnectionConfig 这个类就是读取配置文件中数据库的信息。而定义的接口就是一个获取Connection和释放Connection的两个方法,而抽象了实现了这个接口并且实现了释放Connection 方法,而ConnectionImpl 这个类继承了那个抽象了并且实现了获取Connection 的方法,而获取Connection 时数据库相关的信息来自于之前类配置文件中的数据,到这里我们已经能够获取Connection 实例了,而之后的工厂类,工厂类有两个方法,一个是获取Connection 实例的方法而另一个就是释放Connection 资源的方法。而工厂类中的获取Connection 实例的方法就是实例化一个ConnectionImpl 类这样就能调用ConnectionImpl 类的相关方法来获取Connection 实例,ok 到这里我们调用工厂类的响应方法就能获取Connection。在整个过程中和数据库相关的只有一个地方那就是数据库配置文件,这里配置了那个数据库的信息我们就获取那个数据库的链接如果想要MySQL的数据库链接则配置MySQL 相关信息而配置Oracle 则一样配置Oracle 数据库的相关信息而代码一个都不用改,这样就方便多了。
第一种方式中我们使用了一个配置文件,也就是数据库配置文件这种配置方式中我们只需要修改配置文件就能修改获取的数据库链接而还有一种方式就是除了数据库配置文件还有类名配置文件,这样我们可以有多个数据库配置文件,每一个配置一种数据库,而类名配置文件中的类名就是实现接口和抽象类的那个,也就是获取具体数据库链接的类,这个Factory 类什么的都一样了,和上面的相比就是多了一个配置文件,这个配置文件中配置了类名,这样不用修改数据库配置文件而是修改类名配置文件来改变获取的数据库的链接。
二、第二种实现方式代码:
1、数据库配置文件:MySqlConnectionConfig.properties(需要几个数据库就可以配置几个数据库配置文件这里是mysql的配置)
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/music?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
user=root
password=admin
2、获取对应数据库配置文件的类:MySqlConnectionConfig.java
package jdbc;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
*@author WHD
*data 2016年2月15日
*/
public class MySqlConnectionConfig {
private static Properties prop = new Properties();
static {
try {
//InputStream input = ClassLoader.getSystemResourceAsStream("MySqlConnectionConfig.properties");
//InputStream input = MySqlConnectionConfig.class.getClassLoader().getSystemResourceAsStream("MySqlConnectionConfig.properties");
//prop.load(input);
prop.load(MySqlConnectionConfig.class.getClassLoader().getResourceAsStream("MySqlConnectionConfig.properties"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String driver = prop.getProperty("driver");
public static String url = prop.getProperty("url");
public static String user = prop.getProperty("user");
public static String password = prop.getProperty("password");
}
3、获取Connection 连接是Connection资源释放的接口:IDBConnection.java
package jdbc;
import java.sql.Connection;
/**
* @author WHD data 2016年2月15日
*/
public interface IDBConnection {
public abstract Connection getConnection();
public abstract void closeConnection(Connection conn);
}
4、实现Connection连接和Connection 资源释放的抽象类:AbstractConnectionImpl.java
package jdbc;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @author WHD data 2016年2月15日
*/
public abstract class AbstractConnectionImpl implements IDBConnection {
public void closeConnection(Connection conn) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Connection getConnection() {
// TODO Auto-generated method stub
return null;
}
}
5、具体数据库连接获取的实现了:MySqlConnectionImpl.java (因为这里使用了mysql为例,但是我们在使用的过程配置几个数据库配置文件,就要有几个具体的连接获取类)
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
*@author WHD
*data 2016年2月15日
*/
public class MySqlConnectionImpl extends AbstractConnectionImpl {
@Override
public Connection getConnection() {
// TODO Auto-generated method stub
Connection conn = null;
try {
Class.forName(MySqlConnectionConfig.driver);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn = DriverManager.getConnection(MySqlConnectionConfig.url,
MySqlConnectionConfig.user, MySqlConnectionConfig.password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
@Override
public void closeConnection(Connection conn) {
// TODO Auto-generated method stub
super.closeConnection(conn);
}
public static void main(String[]args){
MySqlConnectionImpl imp= new MySqlConnectionImpl();
imp.getConnection();
}
}
6、对象配置文件:DBConfig.properties(这里面配置那个数据库Connection 连接获取类的类名称就获取那个数据库Connection实例)
//这里配置了Mysql 实现类的,当然也可以配置oracle sqlserver 等数据库Connection连接获取类的类名称。
className=jdbc.MySqlConnectionImpl
7、类名称配置文件中值获取的类:DBConnectionConfig.java
package jdbc;
import java.io.IOException;
import java.util.Properties;
/**
*@author WHD
*data 2016年2月15日
*/
public class DBConnectionConfig {
//对象文件配置
private static Properties prop = new Properties();
static {
try {
prop.load(DBConnectionConfig.class.getClassLoader()
.getResourceAsStream("DBConfig.properties"));
System.out.println( prop.getProperty("className"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 重配置文件中获取的类名称
public static String className = prop.getProperty("className");
}
8、获取对应数据库连接的工程类:DBConnectionFactory.java
package jdbc;
/**
*@author WHD
*data 2016年2月15日
*/
public class DBConnectionFactory {
//定义一个接口
private static IDBConnection instance;
//同步锁
private static Object initLock = new Object();
public static IDBConnection getInstance() {
if (instance == null) {
synchronized (initLock) {
// 这里的名称就是类配置文件中配置的类型名称即 7 中获取的类名称
String className= (DBConnectionConfig.className);
try {
instance = (IDBConnection) Class.forName(className).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return instance;
}
}
9、调用工厂类的方法获取数据库连接和释放:DBConnection.java
package jdbc;
import java.sql.Connection;
/**
* @author WHD data 2016年2月15日
*/
public class DBConnection {
public static Connection getConnection() {
/**
* 用户无需了解底层是如何实现的,它也不需要关心使用的是哪种数据库
*/
IDBConnection service = DBConnectionFactory.getInstance();
Connection conn = service.getConnection();
return conn;
}
public static void closeConnection(Connection conn) {
IDBConnection service = DBConnectionFactory.getInstance();
service.closeConnection(conn);
}
}
ok 到这里整个过程已完成,通过和第一种方法的比较我们发现第二种方式写的代码比第一种方式多,因为只要需要什么数据库他就是要写配置文件,配置文件的读取类以及Connection 链接获取类,类名称配置文件以及类名称配置文件数据获取的类,所以我们发现第二种方式写了很多重复的代码,那就问题来了既然第二种方式写了这么多重复的代码来获取对应数据库的连接而第一种方式只是简单的修改了数据库配置文件那为何还要第二种对问题就在这里,第一种方式写的重复代码少,配置文件少,但是Connection连接类类名称是直接写死在了工厂类中,而第二种这种方式是从配置文件中读取那个类名称,可以说完全解耦,所以第二种方式带来的好处就是低耦合。