dao中通过oracle查询list,从数据库得到的结果集存放到List集合中

一、业务阐述

在开发中查询的数据库结果集,既要连接数据库、执行数据库操作、关闭数据库,还要把结果集的记录人为的设置到自己封装的DAO中等一系列的重复代码。

本文主要是想解决:用户只需要得到数据库连接,写sql语句,自己封装dao,其余的操作由封转的小框架解决这些重复的工作,用户得到的只是一个集合List。

List里面的元素有集合Map其中key是数据库中的字段类型,value是字段类型对应的值这个函数

DBUtil.executeQuery(con, sql)

List还提供集合元素存放的是dao对象,一条数据库记录对应一个dao对象,此函数是

DBUtil.executeQuery(con, sql,Vehicle.class)

以下提供源码的叙述

二、源码解说

测试类

Main.java代码

f3360644493f501869c6df8b23eb66ed.png

package com.hewen.dao.manage;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.List;

public class Main

{

public static void main(String[] args)

{

Connection con;

try {

con = DBTest.getCon();

} catch (SQLException e) {

e.printStackTrace();

return;

}

PreparedStatement pst = null;

ResultSet rs = null;

String sql = "select * from t_vehicle t where t.vehicle_id<4";

/**

* 该方法用到的技术是通过结果集的列属性的性质得到,没有用到反射机制

* 这个测试用例也是把查询的结果集放到List集合

* 里面的元素是集合Map,key是数据库中的字段类型,value是

* 字段类型对应的值,

* 查询的结果如:[{KIND_ID=1, DEF_FLAG=null, CHANNELNO=1, SN=陆震,(822)22911,13771000789,

* BUYDATE=2010-02-26, DELETETIME=null, STAMP=2010-02-26, REGDATE=null, ISDELETED=0,

* VEHICLE_ID=2, NUMBER_PLATE=苏B10001, VEHICLESTATE=待命状态(对应现场返回), USEDATE=2010-02-26,

* INTERPHONENO=null, NUMBER_PLATE_TYPE_ID=4, TEL2=null, STYLE=null, COLOR=null,

* INTERPHONEID=null, LASTMAINTAINTIME=null, INITDISTANCE=0, LAST_UPDATE_TIME=2010-02-26,

*  REMARK=null, TEL=null, SUPERVISER=null},

*  {KIND_ID=3, DEF_FLAG=null, CHANNELNO=1, SN=陆震,

*  (822)22911,13771000789, BUYDATE=2010-02-26, DELETETIME=null, STAMP=2010-02-26,

*  REGDATE=null, ISDELETED=0, VEHICLE_ID=3, NUMBER_PLATE=苏B90003,

*  VEHICLESTATE=待命状态(对应现场返回), USEDATE=2010-02-26, INTERPHONENO=null,

*  NUMBER_PLATE_TYPE_ID=4, TEL2=13151000793, STYLE=面包车, COLOR=白, INTERPHONEID=null,

*  LASTMAINTAINTIME=null, INITDISTANCE=0, LAST_UPDATE_TIME=2010-02-26, REMARK=null,

*   TEL=22916, SUPERVISER=杨兴华}]

*/

try {

List list=DBUtil.executeQuery(con, sql);

System.out.println(list);

} catch (SQLException e) {

e.printStackTrace();

}

/**

* 这个测试用例只是把查询的结果集中的某一条记录映射到了dao对象中,

* 查询的结果如:

* vehicle:vehicle_id: 2 numberPlate: 苏B10001 deleteDate: null

vehicle:vehicle_id: 3 numberPlate: 苏B90003 deleteDate: null

*/

/*  try {

pst = con.prepareStatement(sql);

rs = pst.executeQuery();

while(rs.next()){

Vehicle r = (Vehicle) DBUtil.getFirstObjectFromRs(rs, Vehicle.class);

System.out.println("vehicle:" + r);

}

} catch (SQLException e) {

e.printStackTrace();

}finally{

DBUtil.closeRs(rs);

DBUtil.closePst(pst);

DBUtil.closeCon(con);

}*/

/**

* 方法是用的反射机制

* 这个测试用例是测试executeQuery函数,把查询的结果集放到List集合

* 并且集合元素存放的是dao对象,一条数据库记录对应一个dao对象,

* 打印出来的结果如:

* [vehicle_id: 2 numberPlate: 苏B10001 deleteDate: null,

* vehicle_id: 3 numberPlate: 苏B90003 deleteDate: null]

*

*/

/*  try {

List list=DBUtil.executeQuery(con, sql,Vehicle.class);

System.out.println(list);

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}*/

}

}

封装dao DBUtil类

Java代码

f3360644493f501869c6df8b23eb66ed.png

package com.hewen.dao.manage;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.lang.reflect.Type;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

import java.sql.Statement;

import java.sql.Types;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/***

* 注意利用查询出数据库的一条记录映射到相应的dao中,写相应的dao一定要注意字段,一定

* 要与数据库的记录字段相对应,大小写可以忽略,但是字段不一致就返回错误的数据

*

* private static Object getValueFromRs(ResultSet rs, String fieldName, Type t) throws SQLException

* 此接口有个小的问题就是如果,获取的字段值是空值或者为null,而你自己的需求就是想要获取的字段为一个

* 默认的值,那就只需要客户该写这个方法,进行判断就可以

* @author Administrator

*

*/

public class DBUtil {

/**

* 对操作的数据库回滚

* @param con 对数据库操作所得到的链接

*/

public static void rollBack(Connection con){

try {

con.rollback();

} catch (SQLException e) {

e.printStackTrace();

}

}

/***

*

* @param con 数据库jdbc链接

* @param sql 执行的sql语句

* @return 返回查询的记录数,记录存储在集合List里面,

* 里面的元素是集合Map,key是数据库中的字段类型,value是

* 字段类型对应的值

* @throws SQLException

*/

public static List> executeQuery(Connection con, String sql) throws SQLException{

PreparedStatement pst = null;

ResultSet rs = null;

try {

pst = con.prepareStatement(sql);

rs = pst.executeQuery();

return getListFromRsLowerCase(rs);

}finally{

closeRs(rs);

closePst(pst);

}

}

/***

*  执行sql语句,把结果集存放到List集合里,集合的元素是dao对象

* @param con 数据库得到的链接

* @param sql 执行查询的sql语句

* @param c   把一条条记录要映射的dao类中的对象中去

* @return

* @throws SQLException

*/

public static List executeQuery(Connection con, String sql, Class> c) throws SQLException{

PreparedStatement pst = null;

ResultSet rs = null;

try {

pst = con.prepareStatement(sql);

rs = pst.executeQuery();

return getListFromRs(rs, c);

}finally{

closeRs(rs);

closePst(pst);

}

}

/**

* 得到结果集存储到list中

* @param rs 查询的结果集

* @return

* @throws SQLException

*/

public static List> getListFromRs(ResultSet rs) throws SQLException{

ResultSetMetaData md = rs.getMetaData();//得到结果集列的属性

int columns = md.getColumnCount();//得到记录有多少列

int i;

List> list = new ArrayList>();

while(rs.next()){

Map map = new HashMap();

for(i = 0; i 

map.put(md.getColumnName(i + 1), getValueByType(rs, md.getColumnType(i + 1), md.getColumnName(i + 1)));

}

list.add(map);

}

return list;

}

/**

* 这个与getListFromRs(ResultSet rs)差不多,只是把数据库的字段变成小写

*

* @param rs

* @return

* @throws SQLException

*/

public static List> getListFromRsLowerCase(ResultSet rs) throws SQLException{

ResultSetMetaData md = rs.getMetaData();

int columns = md.getColumnCount();

int i;

List> list = new ArrayList>();

while(rs.next()){

Map map = new HashMap();

for(i = 0; i 

map.put(md.getColumnName(i + 1).toLowerCase(), getValueByType(rs, md.getColumnType(i + 1), md.getColumnName(i + 1)));

}

list.add(map);

}

return list;

}

/**

* 这个与getListFromRs(ResultSet rs)功能一样,只是把数据库的字段变成大写

* @param rs

* @return

* @throws SQLException

*/

public static List> getListFromRsUpperCase(ResultSet rs) throws SQLException{

ResultSetMetaData md = rs.getMetaData();

int columns = md.getColumnCount();

int i;

List> list = new ArrayList>();

while(rs.next()){

Map map = new HashMap();

for(i = 0; i 

map.put(md.getColumnName(i + 1).toUpperCase(), getValueByType(rs, md.getColumnType(i + 1), md.getColumnName(i + 1)));

}

list.add(map);

}

return list;

}

/***

*

* @param rs 查询的结果集

* @param c  集合元素存放的dao对象

* @return

* @throws SQLException

*/

public static List getListFromRs(ResultSet rs, Class> c) throws SQLException{

List list = new ArrayList();

try {

while(rs.next()){

Object o = initObjectFromRsIfExist(rs, c);

list.add(o);

}

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

}

return list;

}

/**

*

* @param rs 查询的结果集

* @param c 结果集一条记录,而一条记录所对应的dao类

* @return

* @throws SQLException

*/

public static Object getFirstObjectFromRs(ResultSet rs, Class> c) throws SQLException{

Object o = null;

try {

o = initObjectFromRsIfExist(rs, c);

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

return o;

}

/***

*

* @param rs 查询出来的结果集

* @param type SQL type from java.sql.Types

* @param name 数据库记录所对应的字段名称

* @return 返回一条记录的一个列值

* @throws SQLException

*/

private static Object getValueByType(ResultSet rs, int type, String name) throws SQLException{

switch(type){

case Types.NUMERIC:

return rs.getLong(name);

case Types.VARCHAR:

//if(rs.getString(name)==null){

//return "";

//}

return rs.getString(name);

case Types.DATE:

//if(rs.getDate(name)==null){

//return System.currentTimeMillis();

//  }

return rs.getDate(name);

case Types.TIMESTAMP:

return rs.getTimestamp(name).toString().substring(0,rs.getTimestamp(name).toString().length()-2);

case Types.INTEGER:

return rs.getInt(name);

case Types.DOUBLE:

return rs.getDouble(name);

case Types.FLOAT:

return rs.getFloat(name);

case Types.BIGINT:

return rs.getLong(name);

default:

return rs.getObject(name);

}

}

/***

* 查询dao映射的字段是否在记录在数据库包含的字段

* @param rs 查询的记录集

* @param fieldName dao映射的字段

* @return 如果包含在数据库记录集里面,返回true,否则false

* @throws SQLException

*/

private static boolean rsContainsFields(ResultSet rs, String fieldName) throws SQLException{

ResultSetMetaData md = rs.getMetaData();

for(int i = 0; i 

if(md.getColumnName(i + 1).equalsIgnoreCase(fieldName)){

return true;

}

}

return false;

}

/***

* 这个函数与initObjectFromRsIfExist函数实现的功能是一样,只是

* 没有判断dao中的字段是否与数据库记录所定义的字段是一样的,

* 没有判断时如果自己设置的dao字段与数据库的字段不一致就会报异常

* @param rs

* @param c

* @return

* @throws InstantiationException

* @throws SQLException

* @throws IllegalAccessException

*/

private static Object initObjectFromRs(ResultSet rs, Class> c) throws InstantiationException, SQLException, IllegalAccessException{

Object o = c.newInstance();

Method[] methods = o.getClass().getMethods();

for(Method m: methods){

if(m.getName().startsWith("set")){

try {

m.invoke(o, getParamValueFromRs(rs, m));

} catch (IllegalArgumentException e) {

throw new RuntimeException("IllegalArgumentException:" + e + "\nMethods:" + m.getName());

} catch (InvocationTargetException e) {

throw new RuntimeException("InvocationTargetException:" + e + "\nMethods:" + m.getName());

}

}

}

return o;

}

/***

*

* 把数据库的一条记录映射到相应的dao对象中,

* 如果dao中的字段与数据库字段不一致,返回的就是dao数据类型定义的默认值

* 如:dao的字段long vehicleID;而数据库的字段是vehicle_id,那么返回的

* 就定义的默认值0.

* @param rs 查询的结果集

* @param c 结果集一条记录,而一条记录所对应的dao类

* @return

* @throws SQLException

* @throws IllegalAccessException

* @throws InstantiationException

*/

private static Object initObjectFromRsIfExist(ResultSet rs, Class> c) throws SQLException, IllegalAccessException, InstantiationException{

Object o = c.newInstance();//一条记录的dao,新建对象

Method[] methods = o.getClass().getMethods();//dao对象所有的方法

String field;

for(Method m: methods){

//得到dao字段,如getRegdate,转换成Regdate

field = m.getName().substring(3);

//查询dao映射的字段是否在记录在数据库包含的字段,dao方法对set开头的方法进行处理

//因为要将结果集映射到dao里面

if(m.getName().startsWith("set") && rsContainsFields(rs, field)){

try {

m.invoke(o, getParamValueFromRs(rs, m));

} catch (IllegalArgumentException e) {

throw new RuntimeException("IllegalArgumentException:" + e + "\nMethods:" + m.getName());

} catch (InvocationTargetException e) {

throw new RuntimeException("InvocationTargetException:" + e + "\nMethods:" + m.getName());

}

}

}

return o;

}

/***

*

* @param rs 查询的结果集

* @param m  dao映射字段对应的一个set方法

* @return

* @throws SQLException

*/

private static Object getParamValueFromRs(ResultSet rs, Method m) throws SQLException

{

String fieldName = m.getName().substring(3);

Type type = m.getGenericParameterTypes()[0];//获取set方法参数的类型

return getValueFromRs(rs, fieldName, type);

}

/**

* 获取数据库一条记录的一个列值

* @param rs 查询的结果集

* @param fieldName dao数据字段,也就是数据库记录的数据字段类型

* @param t 参数的数据类型

* @return

* @throws SQLException

*/

private static Object getValueFromRs(ResultSet rs, String fieldName, Type t) throws SQLException{

String type = t.toString();

try{

if(type.equals("int") || type.equals("class java.lang.Integer")){

return rs.getInt(fieldName);

}else if(type.equals("float") || type.equals("class java.lang.Float")){

return rs.getFloat(fieldName);

}else if(type.equals("double") || type.equals("class java.lang.Double")){

return rs.getDouble(fieldName);

}else if(type.equals("long") || type.equals("class java.lang.Long")){

return rs.getLong(fieldName);

}else if(type.equals("class java.lang.String")){

return rs.getString(fieldName);

}else if(type.equals("class java.sql.Timestamp")){

return rs.getTimestamp(fieldName);

}else if(type.equals("class java.sql.Date")){

return rs.getDate(fieldName);

}else if(type.equals("class java.sql.Time")){

return rs.getTime(fieldName);

}

}catch(SQLException e){

throw new SQLException("SQLException when get field:" + fieldName + "\n" + e);

}

throw new RuntimeException("getValueFromRsByField fail, field type is:" + type + ",field name is:" + fieldName);

}

/***

* 关闭数据库多个结果集

* @param rss

*/

public static void closeRs(ResultSet... rss){

for(ResultSet rs: rss){

if(rs != null){

try {

rs.close();

} catch (SQLException e) {

}

}

}

}

/**

* 关闭数据库多个psts

* @param psts

*/

public static void closePst(Statement... psts){

for(Statement pst: psts){

if(pst != null){

try {

pst.close();

} catch (SQLException e) {

}

}

}

}

/**

* 关闭数据库所得到的多个链接

* @param cons

*/

public static void closeCon(Connection... cons){

for(Connection con: cons){

if(con != null)

{

try {

con.close();

} catch (SQLException e) {

}

}

}

}

}

连接Oracle数据库类

Dbtest.java代码

f3360644493f501869c6df8b23eb66ed.png

package com.hewen.dao.manage;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

/***

* 这个是连接Oracle数据库

* @author Administrator

*

*/

public class DBTest {

public static Connection getCon() throws SQLException{

try {

Class.forName("oracle.jdbc.driver.OracleDriver");

} catch (ClassNotFoundException e) {

e.printStackTrace();

return null;

}

String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";

String user = "avls";

String password = "1";

return DriverManager.getConnection(url, user, password);

}

}

封装的dao类

Vehicle.java代码

f3360644493f501869c6df8b23eb66ed.png

package com.hewen.dao.manage;

import java.sql.Date;

import java.util.ArrayList;

import java.util.List;

public class Vehicle{

private long vehicle_Id;//车牌ID

private String number_plate;//车牌号码

private String def_flag;//车牌自定义别名

private int number_plate_type_id;//拍照类型id

private int kind_id;//车辆类型ID,如物流、出租等

private String style;//车辆品牌如:夏利、奔驰、本田等

private String color;//车辆颜色

private String sn;//序列号

private String interphoneid;//对讲机身份码

private String interphoneno;//对讲机号

private int channelno;//频道号

private float initdistance;//初始里程

private Date lastmaintaintime;//最后保养时间

private String vehiclestate;//车辆状态,如正常使用,作废等

private Date buydate;//购买时间

private Date usedate;//使用时间

private Date regdate;//登记时间

private int isdeleted;//是否删除

private Date deletedate;//删除时间

private Date last_update_time;//最后更新时间

private String remark;//备注

private Date stamp;//入库时间

private String superviser;//责任人姓名

private String tel;//责任人电话一

private String tel2;//责任人电话2

public String getRemark() {

return remark;

}

public void setRemark(String remark) {

this.remark = remark;

}

public String toString(){

return "vehicle_id: "+this.vehicle_Id+" numberPlate: "+this.number_plate+" deleteDate: "+this.deletedate;

}

//@Override

public String tagetTableName() {

return "t_used_vehicle";

}

//@Override

public List unEditFields() {

List list = new ArrayList();

list.add("remark");

return list;

}

public String getNumber_plate() {

return number_plate;

}

public void setNumber_plate(String number_plate) {

this.number_plate = number_plate;

}

public String getDef_flag() {

return def_flag;

}

public void setDef_flag(String def_flag) {

this.def_flag = def_flag;

}

public int getNumber_plate_type_id() {

return number_plate_type_id;

}

public void setNumber_plate_type_id(int number_plate_type_id) {

this.number_plate_type_id = number_plate_type_id;

}

public int getKind_id() {

return kind_id;

}

public void setKind_id(int kind_id) {

this.kind_id = kind_id;

}

public String getStyle() {

return style;

}

public void setStyle(String style) {

this.style = style;

}

public String getColor() {

return color;

}

public void setColor(String color) {

this.color = color;

}

public String getSn() {

return sn;

}

public void setSn(String sn) {

this.sn = sn;

}

public String getInterphoneid() {

return interphoneid;

}

public void setInterphoneid(String interphoneid) {

this.interphoneid = interphoneid;

}

public String getInterphoneno() {

return interphoneno;

}

public void setInterphoneno(String interphoneno) {

this.interphoneno = interphoneno;

}

public int getChannelno() {

return channelno;

}

public void setChannelno(int channelno) {

this.channelno = channelno;

}

public float getInitdistance() {

return initdistance;

}

public void setInitdistance(float initdistance) {

this.initdistance = initdistance;

}

public Date getLastmaintaintime() {

return lastmaintaintime;

}

public void setLastmaintaintime(Date lastmaintaintime) {

this.lastmaintaintime = lastmaintaintime;

}

public String getVehiclestate() {

return vehiclestate;

}

public void setVehiclestate(String vehiclestate) {

this.vehiclestate = vehiclestate;

}

public Date getBuydate() {

return buydate;

}

public void setBuydate(Date buydate) {

this.buydate = buydate;

}

public Date getUsedate() {

return usedate;

}

public void setUsedate(Date usedate) {

this.usedate = usedate;

}

public Date getRegdate() {

return regdate;

}

public void setRegdate(Date regdate) {

this.regdate = regdate;

}

public int getIsdeleted() {

return isdeleted;

}

public void setIsdeleted(int isdeleted) {

this.isdeleted = isdeleted;

}

public Date getDeletedate() {

return deletedate;

}

public void setDeletedate(Date deletedate) {

this.deletedate = deletedate;

}

public Date getLast_update_time() {

return last_update_time;

}

public void setLast_update_time(Date last_update_time) {

this.last_update_time = last_update_time;

}

public Date getStamp() {

return stamp;

}

public void setStamp(Date stamp) {

this.stamp = stamp;

}

public String getSuperviser() {

return superviser;

}

public void setSuperviser(String superviser) {

this.superviser = superviser;

}

public String getTel() {

return tel;

}

public void setTel(String tel) {

this.tel = tel;

}

public String getTel2() {

return tel2;

}

public void setTel2(String tel2) {

this.tel2 = tel2;

}

public long getVehicle_Id() {

return vehicle_Id;

}

public void setVehicle_Id(long vehicle_Id) {

this.vehicle_Id = vehicle_Id;

}

}

运行的结果

运行的结果代码

f3360644493f501869c6df8b23eb66ed.png

[{vehiclestate=待命状态(对应现场返回), vehicle_id=2, interphoneid=null, deletetime=null, number_plate=苏B10001, regdate=null, initdistance=0, superviser=null, style=null, number_plate_type_id=4, tel=null, buydate=2010-02-26, isdeleted=0, kind_id=1, channelno=1, usedate=2010-02-26, remark=null, sn=陆震,(822)22911,13771000789, last_update_time=2010-02-26, interphoneno=null, color=null, tel2=null, stamp=2010-02-26, lastmaintaintime=null, def_flag=null}, {vehiclestate=待命状态(对应现场返回), vehicle_id=3, interphoneid=null, deletetime=null, number_plate=苏B90003, regdate=null, initdistance=0, superviser=杨兴华, style=面包车, number_plate_type_id=4, tel=22916, buydate=2010-02-26, isdeleted=0, kind_id=3, channelno=1, usedate=2010-02-26, remark=null, sn=陆震,(822)22911,13771000789, last_update_time=2010-02-26, interphoneno=null, color=白, tel2=13151000793, stamp=2010-02-26, lastmaintaintime=null, def_flag=null}]

vehicle:vehicle_id: 2 numberPlate: 苏B10001 deleteDate: null

vehicle:vehicle_id: 3 numberPlate: 苏B90003 deleteDate: null

[vehicle_id: 2 numberPlate: 苏B10001 deleteDate: null,

vehicle_id: 3 numberPlate: 苏B90003 deleteDate: null]