连接数据库为什么需要Properties和JDBCFactory,因为连接数据库是一个固定的模式,如果需要换一个数据库连接或者更新查询sql就需要重写代码,那就很麻烦。所以就需要配置文件和JDBCFactory来帮我们简化这些工作。
我们在配置文件中一般会存放jdbc.class,jdbc.url,jdbc.name,jdbc.pass,当然这几个是我自己定义的,第一个是启动类,一般都是com.mysql.jdbc.Driver,接下来就是数据库的url,用户名和密码了。
下面的类中定义了一个mygetProperty(String proName)的方法,通过传入配置文件中的key值来获取对应的value,返回的就是对应的value值,另外这个方法是静态的,所以可以直接用类名.方法名调用。
public class PropertiesUtils {
public static String mygetProperty(String proName) {
String proValue;
Properties prop = new Properties();
try {
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("common.properties");
//输出的是地址
//System.out.println(in);
//此时的prop为一个空的集合“{}”
//System.out.println(prop);
prop.load(new InputStreamReader(in, "utf-8"));
//调用load方法之后,prop被赋值,load方法跟他的名字一样,将读取的字节流转码之后存放进去
//System.out.println(prop);
//这里的getProperty方法是Properties 类里面自带的方法,这个和我们定义的方法没有关系
proValue = (prop.getProperty(proName));
return proValue;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
好了,通过上面的代码我们已经可以拿到配置文件中对应key的value值了,接下来我们就应该进行数据库的连接操作了
public class JDBCConnectionFactory {
//先通过getProperty方法拿到连接数据库必备的四要素
private static Connection connection;
private static String jdbcClass = PropertiesUtils.getProperty("jdbc.class");
private static String jdbcUrl = PropertiesUtils.getProperty("jdbc.url");
private static String jdbcName = PropertiesUtils.getProperty("jdbc.name");
private static String jdbcPass = PropertiesUtils.getProperty("jdbc.pass");
/**
* 从constant中获取JDBC的URL用户名及密码,生成一个连接。
*
* @return
*/
public static Connection jdbcConnection() {
try {
//加载数据库驱动程序(对应的Driver实现类中有注册的静态代码块)
Class.forName(jdbcClass);
// System.out.println(jdbcurl);
//进行数据库的连接
//创建数据库连接:三种连接方案
//方案一:connection = DriverManager.getConnection(jdbcUrl);
//方案二:connection = DriverManager.getConnection(url,user,password);
//方案三:connection = DriverManager.getConnection(url,info);
connection = (Connection) DriverManager.getConnection(jdbcUrl,
jdbcName, jdbcPass);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
//关闭数据库的连接
public static void closequery(ResultSet rs,PreparedStatement ps,Connection con) throws SQLException {
if(rs!=null)
rs.close();
if(ps!=null)
ps.close();
if(con!=null)
con.close();
}
//关闭数据库的连接
public static void close(Statement stmt,Connection con) throws SQLException {
if(stmt!=null)
stmt.close();
if(con!=null)
con.close();
}
}
public class JDBCUtils {
/**
* 查询数据库,可用于select
*
* @param sql
* @param parameter
* @return
* @throws SQLException
*/
public static List<Object> querySQL(String sql, List<Object> parameter) throws SQLException {
List<Object> valueList = new ArrayList<Object>();
Connection connection =null;
PreparedStatement ps=null;
ResultSet rSet=null;
try {
// 获取数据库连接
connection = JDBCConnectionFactory.jdbcConnection();
// 传入的select SQL语句String sql = "select * from person where pname=?";
//ps = conn.prepareStatement(sql);
//设置sql语句中的参数,第一个为sql语句中的参数的?(从1开始),第二个为设置的参数值
//ps.setString(1, "qzy");prepareStatement相当于预处理,后续可以直接在sql中设置参数
//向数据库发出 sql 语句查询,并返回结果集
ps = connection.prepareStatement(sql);
// 执行SQL语句
rSet = ps.executeQuery();
// System.out.println(rSet);
// 循环输入查询到的内容,将结果写入List
while (rSet.next()) {
for (int i = 0; i < parameter.size(); i++) {
// System.out.println("string="+parameter.get(i).toString());
String value = rSet.getString(parameter.get(i).toString());
// System.out.println(value);
valueList.add(value);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCConnectionFactory.closequery(rSet, ps, connection);
}
return valueList;
}
/**
* 更新数据库,可以用于insert、update、delete
*
* @param sql
* @throws SQLException
*/
public static void updateSQL(String sql) throws SQLException {
Connection connection =null;
Statement ps=null;
try {
// 获取数据库连接
connection = JDBCConnectionFactory.jdbcConnection();
// SQL语句
ps = (Statement) connection.createStatement();
ps.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCConnectionFactory.close(ps, connection);
}
// return valueList;
}
}
上面我们可以看到这样那个的连接方式虽然比直接去连数据库要规范化很多,不用每次创建连接的时候都去写连接的语句,但是这样做还是有不少的问题。
通过上面的例子我们可以分析如下几点
1.问题一:数据库连接,使用时就创建,使用完毕就关闭,这样会对数据库进行频繁的获取连接和关闭连接,造成数据库资源浪费,影响数据库性能
设想解决:使用数据库连接池管理数据库连接
2.问题二:将sql语句硬编码到程序中,如果sql语句修改了,那么需要重新编译java代码,不利于维护
设想解决:将sql语句配置到xml文件中,及时sql语句变化了,我们也不需要对java代码进行修改,重新编译
3.问题三:在PreparedStament中设置参数,对占位符设置值都是硬编码到java代码中,不利于维护
设想解决:将sql语句以及占位符和参数都配置到xml文件中
4.问题四:从resultset中遍历结果集时,对表的字段存在硬编码,不利于维护
设想解决:将查询的结果集自动映射为java对象
5.问题五:重复性代码特别多,频繁的try-catch
设想解决:将其整合到一个try-catch代码块中
6.问题六:缓存做的很差,如果存在数据量很大的情况下,这种方式性能特别低
设想解决:集成缓存框架去操作数据库
7.问题七:sql的移植性不好,如果换个数据库,那么sql语句可能要重写
设想解决:在JDBC和数据库之间插入第三方框架,用第三方去生成sql语句