业务背景:系统中所有实体对象都涉及到基本的CRUD操作:
• 所有实体的CUD操作代码基本相同,仅仅发送给数据库的SQL语句不同而已,因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句。
• 实体的R操作,除SQL语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中。
基于上面的业务背景,我们就很有必要简化一下代码了下面来具体看一看下面的几个例子,来比较一下简化代码的优点。
1、 使用传统的方式进行CUD操作
publicvoid insert(Admin admin){
//注:DBConn是我自己定义的一个用来获取连接的工具类
conn = DBConn.getConnction();
String sql ="insert into admin (id,username,password,sex,role )values(?,?,?,?,?)";
try {
ps =conn.prepareStatement(sql);
int index=1;
ps.setInt(index++,admin.getId());
ps.setString(index++,admin.getUsername());
ps.setString(index++,admin.getPassword());
ps.setString(index++,admin.getSex());
ps.setInt(index++,admin.getRole());
ps.executeUpdate();
} catch(SQLException e) {
thrownew RuntimeException(e);
}finally{
DBConn.release(conn, ps);
}
}
publicvoid delete(int id) {
conn = DBConn.getConnction();
String sql ="delete from admin where id =?";
try {
ps =conn.prepareStatement(sql);
int index=1;
ps.setInt(index++, id);
ps.executeUpdate();
} catch(SQLException e) {
thrownew RuntimeException(e);
}finally{
DBConn.release(conn, ps);
}
}
publicvoid update(Admin admin) {
conn = DBConn.getConnction();
String sql ="update admin set username=?,password =?,sex=?,role=? where id =? ";
try {
ps =conn.prepareStatement(sql);
int index=1;
ps.setString(index++,admin.getUsername());
ps.setString(index++,admin.getPassword());
ps.setString(index++,admin.getSex());
ps.setInt(index++,admin.getRole());
ps.setInt(index++,admin.getId());
ps.executeUpdate();
} catch(SQLException e) {
thrownew RuntimeException(e);
}finally{
DBConn.release(conn, ps);
}
}
简化后的相关操作:
Connection con = null;
PreparedStatement ps =null;
ResultSet rs = null;
publicvoid insert(){
Stringsql = "insert intouser (username,password)values(?,?)";
Object[] obj={"ccc","ddd"};
C3p0.update(sql, obj);
}
publicvoid delete(){
String sql ="deletefrom user where id=?";
Object [] obj={4};
C3p0.update(sql, obj);
}
publicvoid update(){
String sql ="updateuser set username=?,password=? where id=?";
Object [] obj={"eee","fff",2};
C3p0.update(sql, obj);
}
//每个方法中就只有这么几行代码看起来就简洁多了。
//另外关于C3P0:
publicclass C3p0 {
//private static Connection con;
// ComboPooledDataSource cpds = newComboPooledDataSource("intergalactoApp");
privatestatic ComboPooledDataSource cpds;
/*static{
cpds = new ComboPooledDataSource("mysql");
}*/
// 或者
static{
cpds = new ComboPooledDataSource("mysql");
try {
cpds.setDriverClass("com.mysql.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/user" );
cpds.setUser("root");
cpds.setPassword("root");
// cpds.setMaxStatements( 180 );
cpds.setMaxIdleTime(6000);
cpds.setMaxPoolSize(40);
cpds.setMinPoolSize(5);
cpds.setInitialPoolSize(10);
cpds.setMaxStatementsPerConnection(20);
} catch(PropertyVetoException e) {
e.printStackTrace();
}
}
publicstatic Connection getConnection() throwsSQLException{
return cpds.getConnection();
}
publicstaticvoid closeDB(Connection con,Statementst,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch(SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch(SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch(SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
publicstaticvoid update(String sql,Object [] obj){
Connection con = null;
PreparedStatement ps =null;
try {
con=C3p0.getConnection();
ps = con.prepareStatement(sql);
for(int i=0;i<obj.length;i++){
ps.setObject(i+1,obj[i]);
}
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
C3p0.closeDB(con,ps, null);
}
}
}
上面介绍的并不包括有关查询的内容,因为查询时会产生结果集而我们并不知道用户到结果集后要进行什么样的操作所以关于简化查询的方法在操作时比较复杂,具体简化方法如下:
例如当查询到结果后将结果封装到一个实体对象中。
//实体对象User.java
publicclass User {
privateintid;
private String username;
private String password;
publicint getId() {
returnid;
}
publicvoid setId(int id) {
this.id = id;
}
public String getUsername() {
returnusername;
}
publicvoid setUsername(Stringusername) {
this.username = username;
}
public String getPassword() {
returnpassword;
}
publicvoid setPassword(Stringpassword) {
this.password = password;
}
}
//自定义的一个类用以获取连接或关闭连接以及相应的查询方法
publicclass C3p0 {
//private static Connection con;
// ComboPooledDataSource cpds = newComboPooledDataSource("intergalactoApp");
privatestatic ComboPooledDataSource cpds;
/*static{
cpds = new ComboPooledDataSource("mysql");
}*/
// 或者
static{
cpds = new ComboPooledDataSource("mysql");
try {
cpds.setDriverClass("com.mysql.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/user" );
cpds.setUser("root");
cpds.setPassword("root");
// cpds.setMaxStatements( 180 );
cpds.setMaxIdleTime(6000);
cpds.setMaxPoolSize(40);
cpds.setMinPoolSize(5);
cpds.setInitialPoolSize(10);
cpds.setMaxStatementsPerConnection(20);
} catch(PropertyVetoException e) {
e.printStackTrace();
}
}
publicstatic Connection getConnection() throwsSQLException{
return cpds.getConnection();
}
publicstaticvoid closeDB(Connection con,Statementst,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch(SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch(SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch(SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
publicstatic Objectselect(String sql,Object[] obj,ResultSetHandler rsh){
Connection con = null;
PreparedStatement ps =null;
ResultSet rs=null;
try {
con=C3p0.getConnection();
ps = con.prepareStatement(sql);
for(int i=0;i<obj.length;i++){
ps.setObject(i+1, obj[i]);
}
rs = ps.executeQuery();
return rsh.handler(rs);
} catch(Exception e) {
// 抛出运行时异常?????
thrownew RuntimeException(e);
}finally{
C3p0.closeDB(con, ps, rs);
}
}
}
//一个处理接口类
publicinterface ResultSetHandler{
public Object handler(ResultSetrs);
}
//一个处理接口实现类
public class ResultSetHandlerImp implementsResultSetHandler{
privateClass clazz;
publicResultSetHandlerImp(Class clazz) {
super();
this.clazz= clazz;
}
publicObject handler(ResultSet rs) {
Objectuser =null;
try{
// 如结果集为空则返回空
if(!rs.next()){
returnnull;
}
// 创建一个clazz对象实例并将其赋给要返回的那个返回值。
user=clazz.newInstance();
// 获取结果集的数据源
ResultSetMetaDatarsmeta= rs.getMetaData();
// 获取结果集中的字段数
intcount = rsmeta.getColumnCount();
// Fieldf = bean.getClass().getField("");
// 循环取出个字段的名字以及他们的值并将其作为值赋给对应的实体对象的属性
for(inti=0;i<count;i++){
// 获取字段名
Stringname = rsmeta.getColumnName(i+1);
// 利用反射将结果集中的字段名与实体对象中的属性名相对应,由于
// 对象的属性都是私有的所以要想访问必须加上getDeclaredField(name)和
// f.setAccessible(true)
Fieldf =user.getClass().getDeclaredField(name);
f.setAccessible(true);
// 将结果集中的值赋给相应的对象实体的属性
f.set(user,rs.getObject(name));
}
}catch (Exception e) {
e.printStackTrace();
}
returnuser;
}
}
最后只需简单的调用即可:
public void select(){
String sql="select * from user where id=?";
Object [] obj={3};
User user = (User) C3p0.select(sql,obj, new ResultSetHandlerImp(User.class));
System.out.println(user.getId());//此处传入一个类类型的对象故User.class
System.out.println(user.getPassword());
System.out.println(user.getUsername());
}
这样每个方法再使用起来就简单多了。赶快优化一下自己的代码吧!