我们知道如何通过JDBC连接并操作数据库,但是每次我们实现增删改查时都会有一大段重复代码,所以本文主要是用实例说明了如何优化那些代码。这只是初步的简单优化。后面我会持续更新的。
你要是忍不急想看主要代码,前往第5步工具类。
1. 建表account
create table account(
id int primary key auto_increment,
name varchar(40),
money float
);character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
2. 连接数据库的配置文件
在这个阶段的学习里,此配置文件可以当做模板来使用,并且里面有很详细的注释。
dbcpConfig.properties
#连接设置
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/testbatch
username=root
password=root
#初始化连接
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000=60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性的格式必须为这样:[属性名=property;]
#注意:"user"与"password"两个属性会被明确传递,因此这里不需要包含它们
connectionProperties=useUnicode=true;characterEncoding=utf8
#指定由连接池所创建的连接的自动提交(auto-commit)状态
defaultAutoCommit=true
#如果没有设置该值,则"setReadOnly"方法将不被调用。(某些驱动并不支持只读模式,如:Infomix)
defaultReadOnly
#driver default 指定由连接池所创建连接的事务级别(TransactionIsolation)
#可用值:NONE,READ_UNCOMMITTED,READ_COMMITTED,REPEATABLE_READ,SERIALIZABLE
defalutTransactionIsolation=READ_COMMITTED
3. 连接池JdbcUtils_DBCP
package cn.itcast.utils;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* Created by yvettee on 2017/9/30.
*/
public class JdbcUtils_DBCP {
private static DataSource ds = null;
static {
try {
InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpConfig.properties");
Properties prop = new Properties();
prop.load(in);
BasicDataSourceFactory factory = new BasicDataSourceFactory();
ds = factory.createDataSource(prop);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
public static void release(Connection conn, Statement st, ResultSet rs) {
if (rs != null) {
try {
rs.close(); //throw new
} catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if (st != null) {
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
}
st = null;
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
4. 实体类Account
package cn.itcast.domain;
/**
* Created by yvettee on 2017/9/30.
*/
public class Account {
private int id;
private String name;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double price) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
5.工具类
JdbcUtils
这个类里面就主要是对增删改查代码的优化了。增删改比较简单,用update一个方法就可以解决,主要就是查询比较复杂。因为查询时根据查询语句的不同,返回的结果集就不一样,不知道怎么处理,但是用户知道。在做开发的过程中,拿到结果集了,不知道怎么处理,就向用户暴露一个接口,你实现接口我这边就调用接口处理。
package cn.itcast.utils;
import java.sql.*;
/**
* Created by yvettee on 2017/9/30.
*/
public class JdbcUtils {
//add update delete
// sql="insert into account(id,name,money) values(?,?,?) Object[]{1,"a",100}"
public static void update(String sql, Object params[]) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils_DBCP.getConnection();
ps = conn.prepareStatement(sql);
//Object params[]替换sql里面的参数
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils_DBCP.release(conn, ps, rs);
}
}
//查找的优化是最难的
public static Object query(String sql, Object params[], ResultSetHandler handler) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils_DBCP.getConnection();
ps = conn.prepareStatement(sql);
//Object params[]替换sql里面的参数
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
//不知道sql语句是怎样的,也就不知道怎么处理rs,但是用户知道怎么处理
rs = ps.executeQuery();
return handler.handler(rs);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils_DBCP.release(conn, ps, rs);
}
return null;
}
}
ResultSetHandler
接口
package cn.itcast.utils;
import java.sql.ResultSet;
/**
* Created by yvettee on 2017/10/2.
*/
//暴露一个处理结果集的接口
public interface ResultSetHandler {
//返回多个值,Object类型
public Object handler(ResultSet rs);
}
BeanHandlerImpl
对接口进行处理
package cn.itcast.utils;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
/**
* Created by yvettee on 2017/10/2.
*/
public class BeanHandlerImpl implements ResultSetHandler {
private Class clazz;
public BeanHandlerImpl(Class clazz) {
this.clazz = clazz;
}
@Override
public Object handler(ResultSet rs) {
try {
if (!rs.next()) {
return null;
}
//创建出封装结果集的bean
Object bean = clazz.newInstance();
//得到结果集的元数据,以获取结果集的信息
ResultSetMetaData meta = rs.getMetaData();
int count = meta.getColumnCount();
for (int i = 0; i < count; i++) {
String name = meta.getColumnName(i + 1);//获取到结果集每列的列名
Object value = rs.getObject(name);
//将获取到的值封装到与bean上相对应的属性上去(反射出bean上与列名相应的属性)
Field f = bean.getClass().getDeclaredField(name);
f.setAccessible(true);
f.set(bean, value);
}
return bean;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
6. 接口以及接口的实现
AccountDao
package cn.itcast.dao.impl;
import cn.itcast.domain.Account;
/**
* Created by yvettee on 2017/10/1.
*/
public interface AccountDao {
void add(Account account);
void delete(int id);
void update(Account account);
Account find(int id);
}
AccountDaoImpl
package cn.itcast.dao.impl;
import cn.itcast.domain.Account;
import cn.itcast.utils.BeanHandlerImpl;
import cn.itcast.utils.JdbcUtils;
/**
* Created by yvettee on 2017/9/30.
*/
public class AccountDaoImpl implements AccountDao {
@Override
public void add(Account account) {
String sql = "insert into account(name,money) values(?,?)";
Object params[] = {account.getName(), account.getMoney()};
JdbcUtils.update(sql, params);
}
@Override
public void delete(int id) {
String sql = "delete from account where id=?";
Object params[] = {id};
JdbcUtils.update(sql, params);
}
@Override
public void update(Account account) {
String sql = "update account set name=?,money=? where id=?";
Object params[] = {account.getName(), account.getMoney(), account.getId()};
JdbcUtils.update(sql, params);
}
@Override
public Account find(int id) {
String sql = "select * from account where id=?";
Object params[] = {id};
return (Account)JdbcUtils.query(sql,params,new BeanHandlerImpl(Account.class));
}
}
7. Junit测试
package cn.itcast.test;
import cn.itcast.dao.impl.AccountDao;
import cn.itcast.dao.impl.AccountDaoImpl;
import cn.itcast.domain.Account;
import org.junit.Test;
/**
* Created by yvettee on 2017/10/1.
*/
public class TestAccount {
@Test
public void testAdd() {
Account a = new Account();
a.setName("车村");
a.setMoney(100.23);
AccountDao dao = new AccountDaoImpl();
dao.add(a);
System.out.println(a);
}
@Test
public void testDelete() {
AccountDao dao = new AccountDaoImpl();
dao.delete(10);
}
@Test
public void testUpdate() {
Account a = new Account();
a.setName("车村");
a.setMoney(100.23);
a.setId(1);
AccountDao dao = new AccountDaoImpl();
dao.update(a);
}
@Test
public void testQuery() {
AccountDao dao = new AccountDaoImpl();
dao.find(1);
System.out.println(dao.find(1));
}
}
本文的源代码:https://github.com/yvettee36/JdbcFrame
对之前写的客户关系管理案例里面的代码进行小小的优化。源代码
上篇:编写自己的JDBC框架之元数据
网友评论