火星文 技术研习社

Noname Cat, Keep Thinking
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

executeSqlDataSet - 类似 SqlHelper 的 Java 实现

Posted on 2008-01-14 16:41  剑廿三  阅读(829)  评论(0编辑  收藏  举报

做成类似 Microsoft.NET SqlHelper 的 Java 实现

用到了 apache-commons-dbutils-1.1 类库

1. 主要程序,Java 的泛型比较古怪,不能做参数,所以CoreTest的构造方法也要跟着古怪一下

package epg.lab.test;
import java.util.*
;
import java.sql.*
;
import java.util.regex.*
;
import java.lang.reflect.*
;
import org.apache.commons.dbutils.*
;

public class CoreTest<T>
 {
    
    
private T emptyEntity = null
;
    
    
public
 CoreTest(T emptyEntity){
        
this.emptyEntity =
 emptyEntity;
    }

    
public List<T>
 executeSqlDataSet(Connection conn, String sql, Object parameterObject){
        List
<T> result = null
;
        String regEx
="@[a-zA-Z_0-9]+"
;
        Pattern p
=
Pattern.compile(regEx); 
        Matcher m
=
p.matcher(sql);
        
        List
<Object> values = new ArrayList<Object>
();
        
while
(m.find()){
            values.add(m.group().substring(
1
));
        }
        String resultSQL 
= m.replaceAll("?"
);
        
        
try
{
             
for(Field f : News.class
.getDeclaredFields()){
                  
if(f.isAnnotationPresent(SqlParameter.class
)){
                      SqlParameter param 
= f.getAnnotation(SqlParameter.class
);
                      
for(int i=0;i<values.size();i++
){
                          
if
(param.field().equals(values.get(i))){
                              
if
(f.isAccessible()){
                                  values.set(i, f.get(parameterObject));
                              }
else
{
                                  Method getter 
= News.class.getMethod(new StringBuffer("get").append(f.getName().substring(0,1).toUpperCase()).append(f.getName().substring(1
)).toString());
                                  
if(getter!=null
){
                                      values.set(i, getter.invoke(parameterObject));
                                  }
else
{
                                      values.set(i, 
null
);
                                  }
                              }
                          }
                      }
                  }
              }
        }
catch
(Exception ex){
            ex.printStackTrace();
        }
        
        PreparedStatement  pstmt 
= null
;
        ResultSet rs 
= null
;
        
try
{
            pstmt 
=
 conn.prepareStatement(resultSQL);
              
            
for(int i=0;i<values.size();i++
){
                pstmt.setObject(i
+1
, values.get(i));
            }
            rs 
=
 pstmt.executeQuery();
            BeanProcessor processor 
= new
 BeanProcessor();
            result 
= processor.toBeanList(rs, this
.emptyEntity.getClass());
        }
catch
 (Exception e) {
            e.printStackTrace();
        }
        
finally
{
            
try { rs.close(); } catch
(Exception e) { }
            
try { pstmt.close(); } catch
(Exception e) { }
        }
        
        
return
 result;
    }

    
/**

     * 
@param args
     
*/

    
public static void main(String[] args) {
        News newsCondition 
= new
 News();
        newsCondition.setId(
1
);
        newsCondition.setTitle(
"央行%"
);
        newsCondition.setPubDate(Calendar.getInstance().getTime());
        
        String sql 
= "SELECT * FROM News_NewsContent WHERE ID>@ID AND Title like @Title OR ID=@ID"
;
        
        CoreTest
<News> test = new CoreTest<News>(new
 News());
        
        List
<News> list = null
;
        Connection conn 
= null
;
        
try
{
            Class.forName(
"com.microsoft.sqlserver.jdbc.SQLServerDriver"
);
            conn 
= DriverManager.getConnection("jdbc:sqlserver://localhost;databaseName=News;user=sa;password=123456"
);
            
            list 
=
 test.executeSqlDataSet(conn, sql, newsCondition);
        }
catch
(Exception ex){
            ex.printStackTrace();
        }
finally
{
            
try{conn.close();conn=null;}catch
(Exception ex){}
        }
        
        
for
(News news : list){
            System.out.print(news.getId());
            System.out.print(news.getTitle());
            System.out.println(news.getPubDate());
        }
    }

}

2. News 类,可以作为查询条件,也可以作为查询结果集的数据行对象。搞了个 SqlParameter Annotation 用来声明类属性对应的数据表字段。

package epg.lab.test;
import java.util.*
;

public class
 News {
    
    @SqlParameter(field
="ID"
)
    
private int
 id;
    @SqlParameter(field
="Title"
)
    
private
 String title;
    @SqlParameter(field
="PubDate"
)
    
private
 Date pubDate;
    
/**

     * 
@return the id
     
*/

    
public int getId() {
        
return
 id;
    }
    
/**

     * 
@param id the id to set
     
*/

    
public void setId(int id) {
        
this.id =
 id;
    }
    
/**

     * 
@return the pubDate
     
*/

    
public Date getPubDate() {
        
return
 pubDate;
    }
    
/**

     * 
@param pubDate the pubDate to set
     
*/

    
public void setPubDate(Date pubDate) {
        
this.pubDate =
 pubDate;
    }
    
/**

     * 
@return the title
     
*/

    
public String getTitle() {
        
return
 title;
    }
    
/**

     * 
@param title the title to set
     
*/

    
public void setTitle(String title) {
        
this.title =
 title;
    }

}

3. SqlParameter Annotation,前面 RUNTIME 的定义是一定要加的,这样才能在运行时反射出来。

package epg.lab.test;
import java.lang.annotation.*
;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface
 SqlParameter {
    
    String field();
    
int sqlType() default
 java.sql.Types.NVARCHAR;
    
boolean output() default false
;

}


运行主程序在 console 会得到:

1经济型酒店正成国内特许加盟项目新宠2006-11-20 20:22:50.0
9央行:采取综合措施合理控制货币信贷增长2006-11-20 20:27:38.0
12央行将积极推动境内机构投资者开展境外投资业务2006-11-20 20:29:15.0
14央行将建立国家反洗钱数据库2006-11-20 20:30:03.0


相比 HQL 的优点是这个东西比较简单,轻量级。这个东西还不完善,例如不能做 WHERE ID IN (...) 。可以参考着做一个依赖 CallableStatement 的存储过程调用方法 executeStoredProcedureDataSet 。