package gonow.dao;import gonow.uitils.JDBCUtil;
import gonow.uitils.Page;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;public class AdministerDAO {
private static Connection connection = null;
static{
connection = JDBCUtil.getConnection();
}

private Class a = null;
private String className;

//插入
public boolean setInsert(Object object) throws Exception{
String sql = "insert into ";
Class c = null;
int leng = 0;
try{
c = object.getClass();
String tableName = c.getName();
int lengs = tableName.length();
int numbers = tableName.lastIndexOf(".")+1;
sql += tableName.substring(numbers, lengs);
Field[] filed = c.getDeclaredFields();
leng = filed.length;
int i = 0;
sql += "(";
}catch(Exception e){
e.printStackTrace();
System.out.println("AdministerDAO出错!!");
}
try{
Method[] m = c.getDeclaredMethods();
Object[] mis = new Object[leng];
String[] nums = new String[leng];
int tt = 0;
for(Method b : m){
String mb = b.toString();
int num = mb.lastIndexOf(".")+1;
if("g".equals(mb.substring(num,num+1))){
int sn = mb.length();
String names = mb.substring(num+3,sn-2);
nums[tt] = names;
System.out.print("字段名: "+names + "  ");  //字段名
Object obj  = b.invoke(object,null);
System.out.println("字段内容" + obj);  //字段内容
mis[tt] = obj;
tt++;
}
}

for(int r = 0;r <leng;r++){
sql += nums[r];
if(r != leng-1){
sql += ",";
}
}
sql += ") values (";
for(int j = 0; j<leng;j++){
sql += "?";
if(j != leng-1){
sql += ",";
}
}
sql += ");";
System.out.println("sql: " + sql);
//Connection connection = JDBCUtil.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
int sk =1;
for(int y = 0; y<leng;y++){
preparedStatement.setObject(sk, mis[y]);
sk++;
}
Integer count = preparedStatement.executeUpdate();
if(null != count){
System.out.println("-----------------执行成功---------------------");
return true;
}
return false;
}catch(Exception e){
e.printStackTrace();
System.out.println("插入出现错误!!");
}
return false;
}
//        修改
public boolean setUpdate(Object object,int idnumber) throws Exception {
String sql = "Update ";
Class c = null;
int leng = 0;
try{
c = object.getClass();
String tableName = c.getName();
int lengs = tableName.length();
int numbers = tableName.lastIndexOf(".")+1;
sql += tableName.substring(numbers, lengs);
Field[] filed = c.getDeclaredFields();
leng = filed.length;
int i = 0;
sql += " set ";
}catch(Exception e){
e.printStackTrace();
System.out.println("SetUpdate出错了!!");
}
try{
Method[] m = c.getDeclaredMethods();
Object[] mis = new Object[leng];
String[] nums = new String[leng];
int tt = 0;
for(Method b : m){
String mb = b.toString();
int num = mb.lastIndexOf(".")+1;
if("g".equals(mb.substring(num,num+1))){
int sn = mb.length();
String names = mb.substring(num+3,sn-2);
nums[tt] = names;
System.out.print("字段名: "+names + "  ");  //字段名
Object obj  = b.invoke(object,null);
System.out.println("字段内容" + obj);  //字段内容
mis[tt] = obj;
tt++;
}
}

for(int r = 0;r <leng;r++){
sql += nums[r] + "=?";
if(r != leng-1){
sql += ",";
}
}
sql += " where ";
Field[] filed = c.getDeclaredFields();
for(Field  aa: filed){
System.out.println("属性名:  " + aa);
}
String ids = filed[0].toString();
int g = ids.lastIndexOf(".")+1;
String id = ids.substring(g,ids.length());
sql += id + "=" + idnumber +";";
System.out.println("sql: " + sql);
//Connection connection = JDBCUtil.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
int sk =1;
for(int y = 0; y<leng;y++){
preparedStatement.setObject(sk, mis[y]);
sk++;
}
Integer count = preparedStatement.executeUpdate();
if(count != null) return true;
}catch(Exception e){
e.printStackTrace();
System.out.println("修改出现错误!!");
}
return false;
} // 有条件查询和无条件查询
public Page findObject(Object object, int pageNo, int pageSize){

System.out.println("findObject(Object object, int pageNo, int pageSize)");
a = object.getClass();
// if(isObject()){
// return findObject(pageNo, pageSize);
// }
Integer count = countObject();
Page page = new Page(pageNo, pageSize, count);
List list = new ArrayList();
Method[] m = a.getDeclaredMethods();
String sql = "select * from ";
sql += className + " where 1=1";
for(Method methods : m){
int end = methods.toString().lastIndexOf("(") + 1;
String s = methods.toString().substring(0,end);
int start = s.lastIndexOf(".") + 1;
String setMethod = methods.toString().substring(start,end-1);
System.out.println("setMethod: " + setMethod);
if("g".equals(setMethod.substring(0, 1))){
try {
Object re = methods.invoke(object, null);
System.out.println("id1: " + re);
//                                   这里请大家说下,如果数据类型是int型,如果是0的时候就不+sql语句,这里不知
//                                   要怎么去判断它,还有其他的数据类型,是否要一一的去判断
if(re != null && !"".equals(re)){
sql += " and " + setMethod.substring(3) + "= '" + methods.invoke(object, null)+"'";
}
// System.out.println("ao:" + re);
} catch (Exception e) {
e.printStackTrace();
System.out.println("findObject()  error!!! ");

}
}
sql += " limit ";
sql += page.getStart() + "," + page.getPageSize() + ";";
System.out.println("-------  findObject2 sql: + "+ sql + "  ---------");
try{
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet rs = preparedStatement.executeQuery();
Field[] f = a.getDeclaredFields();
int leng = f.length;

Method[] setMethods = new Method[leng];
String[] name = new String[leng];
// System.out.println("leng: " + leng);
int i = 0;
for(Method aa : m){
int end = aa.toString().lastIndexOf("(") + 1;
String s = aa.toString().substring(0,end);
int start = s.lastIndexOf(".") + 1;
//System.out.println("start: " + start + " end: " +end);
String setMethod = aa.toString().substring(start,end-1);
//System.out.println("setMethod: " + setMethod);
if("s".equals(setMethod.substring(0,1))){
name[i] = aa.toString().substring(start+3,end-1);
setMethods[i] = aa;
i++;
}
}
// for(int j = 0; j<leng; j++){
// System.out.print(name[j] + " , ");
// }
while(rs.next()){
Object obj = a.newInstance();
for(int k = 0; k<leng;k++){
// System.out.println("@@@@@" + rs.getObject(name[k]));
setMethods[k].invoke(obj, rs.getObject(name[k]));
}
list.add(obj);
}
}catch(Exception e){
e.printStackTrace();
System.out.println("--------------findObject2 is error ------------------");
}
page.setData(list);
return page;
}

public boolean isObject(){
return true;
}


public int countObject(){
// Connection connection = JDBCUtil.getConnection();
String objectName = a.getName();
// System.out.println("objectName: " + objectName);
int num = objectName.lastIndexOf(".") + 1;
className = objectName.substring(num);
System.out.println("clasName: " + className);
String sql = "select count(*) from ";
sql += className + ";";
System.out.println("countObject中的sql语句为: " + sql);
Long count = null;
try{
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet rs = preparedStatement.executeQuery();
while(rs.next()){
count = rs.getLong(1);
//System.out.println("countObject中count: " + count);
}
}catch(Exception e){
e.printStackTrace();
System.out.println("countObject is Exception!!");
}
return count.intValue();
}
}

解决方案 »

  1.   

    粗略看了下,发现几处肤浅的问题,更深层的问题有待其他高人讲解,呵呵。
    1.连接资源使用完未见楼主将其释放,ResultSet未关,PreparedStatement、Statement未关,Connection也未关。连接多了之后系统资源会占用的很厉害,算是不应该出现的遗漏。
    2.try catch中包含的代码太多,只需要包含可能出异常的代码即可,因为据某人统计,try catch中的代码在正常情况下会慢一些,在出异常的情况下会更慢!
    3.统一捕获异常的超类Exception也不推荐,我看楼主有的try catch中除了涉及sql操作外还涉及反射操作,因此此处肯定不止抛出1种或1类异常,建议的方式是截住不同的异常,作不同的对待
    4.sql类异常通常程序中是无法解决的,所以需要向上层抛,否则控制层就无法知晓数据库操作是否成功完成,更无法告诉客户端操作结果。当然,以boolean返回值的方式告知操作成功与否也是不推荐的,因为方法的返回值并不强制调用处接收,这在有时会造成编码人员疏忽大意而出bug
    5.我个人建议把获得连接这一步拿到dao层外,有时候一个请求不仅仅只操作一张表,除非所有表都经由这个dao,这也是不推荐的,因为难以扩展,一般我都是一个表一个dao
    6.很多sql语句的片段是需要反复使用的,楼主可以将其整理成静态变量,不仅提高执行效率,也便于全局修改
    7.拼接sql语句之类的String频繁操作要使用StringBuffer,会大幅提高效率
      

  2.   

    我怎么总觉得你把Hibernian的工作做了
      

  3.   

    除了1楼说的外,认为还有以下 几个问题:
    每一次操作要获取一个新的Connection对象,不能增删改查都用同一个Connection对象.
    还有你的操作没加上上事务处理啊(因为你这操作了好几个对象).
    重复代码太多,看的费劲.
    其他问题多多.
    至于作用如何,自己测试一下就知道啦..
      

  4.   

    楼上说的都很有道理。insert里面有个明显错误:
    sql += ");"; 
    貌似jdbc调用sql不需要分号来结束
    update里面也有个明显错误:
    sql += ",";
    }
    }
    sql += " where "; 
    set a='a',b='b', where ****** 这样的sql跑不起来看到这里觉得代码太长了,懒得看了
      

  5.   

    先说下,我这个代码可以运行,where 后面加一个永真语句,我这样就不用去判断and ,like是要放在那里的,所以我觉得这样写还是可以的,不过我会想下楼上说的话,看怎么做,谢谢你的建议
      

  6.   

    不足之处 首先 记得下回贴代码的时候 请选择 插入源代码 然后把代码贴进去然后 你确认你在做些什么 你考虑到了什么 你在做之前有没有个计划 你想要什么样的东西其次 考虑清楚你现在做的事情对以后的发展 上面那些人说 连接没关闭啊。。TRY CATCH啊 什么的 我觉得目前来说 都不重要 因为现在你的代码乱的一塌糊涂 你的功能也乱的一塌糊涂 不分主次 最后 不能说是你的不足之处吧 算是我的建议 如果你想做一个只需要放一个CLASS就能进行增删改差的东西的话 不是不让你做 首先你要想明白为什么很多人没做 是因为技术实现不了 还是做出来的东西不适应实际情况 如果说你做完了的话 你觉得你这个东西的价值 或者优点 在哪里具体代码我没看 
      

  7.   

    看了下开头,一个connection打天下,多线程问题。
      

  8.   

    Connection 是珍贵资源,敬请楼主珍惜! 
      

  9.   

    楼主   一个dao类的封装   有这么麻烦吗   看了你的代码   有点同意2楼的看法
      

  10.   

    封装应该根据业务吧~
      太过具体的封装还不如不封。
         Java的反射效率不敢恭维。
      

  11.   


    package xindou.dao;import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;import xindou.utils.JDBCConn;
    import xindou.utils.MethodMap;
    import xindou.utils.Page;public class AdministerDAO {
    private static Connection connection = null;
    static{
    connection = JDBCConn.getConnection();
    }

    private Class a = null;
    private String className;

    //增加方法
    public boolean setInsert(Object object) throws Exception{
    String sql = "insert into ";
    Class c = null;
    int leng = 0;
    try{
    //反射
    c = object.getClass();
    //获取数据库名
    String tableName = c.getName();
    int numbers = tableName.lastIndexOf(".")+1;
    sql += tableName.substring(numbers).toLowerCase();
    //获取类或接口声明的所有字段
    Field[] filed = c.getDeclaredFields();
    //获取Field的长度
    leng = filed.length;
    // int i = 0;
    sql += "(";
    }catch(Exception e){
    e.printStackTrace();
    System.out.println("AdministerDAO出错!!");
    }
    try{
    //反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
    Method[] m = c.getDeclaredMethods();
    //用来保存方法
    String[] means = new String[leng];
    //用来保存方法的内容
    Object[] parameter = new Object[leng];
    int tt = 0;
    for(Method methodName : m){
    //以 String 形式返回此 Method 对象表示的方法名称
    String mb = methodName.getName();
    //获取get方法
    if(mb.startsWith("get")){
    // int sn = mb.length();
    //获取属性名,保存到means中,
    String names = mb.substring(3).toLowerCase();
    means[tt] = names;
    //通过get方法取得各个属性对应的值
    Object obj  = methodName.invoke(object,null);
    //保存到parameter中,与means一一对应
    parameter[tt] = obj;
    tt++;
    }
    }
    //拼凑sql语句
    for(int r = 0;r <leng;r++){
    sql += means[r];
    if(r != leng-1){
    sql += ", ";
    }
    }
    sql += ") values (";
    for(int j = 0; j<leng;j++){
    sql += "?";
    if(j != leng-1){
    sql += ",";
    }
    }
    sql += ");";
    //到此,sql语句拼凑完毕
    System.out.println("sql: " + sql);
    //创建preparedStatement对象
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    //把Object中的数据写到preparedStatement中
    int sk =1;
    for(int y = 0; y<leng;y++){
    preparedStatement.setObject(sk, parameter[y]);
    sk++;
    }
    //判断是否插入成功
    Integer count = preparedStatement.executeUpdate();
    if(null != count){
    System.out.println("-----------------执行成功---------------------");
    return true;
    }
    return false;
    }catch(Exception e){
    e.printStackTrace();
    System.out.println("插入出现错误!!");
    }
    return false;
    }

    //修改
    public boolean setUpdate(Object object,int idnumber) throws Exception {
    String sql = "Update ";
    Class c = null;
    Field[] filed = null;
    int leng = 0;
    try{
    //反射
    c = object.getClass();
    //获取数据库名
    String tableName = c.getName();
    int numbers = tableName.lastIndexOf(".")+1;
    sql += tableName.substring(numbers).toLowerCase();
    //获取类或接口声明的所有字段
    filed = c.getDeclaredFields();
    //获取Field的长度
    leng = filed.length;
    sql += " set ";
    }catch(Exception e){
    e.printStackTrace();
    System.out.println("SetUpdate出错了!!");
    }
    try{
    Method[] m = c.getDeclaredMethods();
    //用来保存方法
    String[] means = new String[leng];
    //用来保存方法的内容
    Object[] parameter = new Object[leng];
    int tt = 0;
    for(Method methodName : m){
    //以 String 形式返回此 Method 对象表示的方法名称
    String mb = methodName.getName();
    //获取get方法
    if(mb.startsWith("get")){
    //获取属性名,保存到means中,
    String names = mb.substring(3).toLowerCase();
    means[tt] = names;
    //通过get方法取得各个属性对应的值
    Object obj  = methodName.invoke(object,null);
    //保存到parameter中,与means一一对应
    parameter[tt] = obj;
    tt++;
    }
    }

    for(int r = 0;r <leng;r++){
    //拼凑sql语句
    sql += means[r] + "=?";
    if(r != leng-1){
    sql += ", ";
    }
    }
    sql += " where ";
    String ids = filed[0].toString();
    int g = ids.lastIndexOf(".")+1;
    String id = ids.substring(g,ids.length());
    sql += id + "=" + idnumber +";";
    System.out.println("sql: " + sql);
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    //把Object中的数据写到preparedStatement中
    int sk =1;
    for(int y = 0; y<leng;y++){
    preparedStatement.setObject(sk, parameter[y]);
    sk++;
    }
    Integer count = preparedStatement.executeUpdate();
    if(count != null) {
    System.out.println("-------------修改成功---------------");
    return true;
    }
    }catch(Exception e){
    e.printStackTrace();
    System.out.println("修改出现错误!!");
    }
    return false;
    }

    //条件查询  分页
    public Page findObject(Object object, int pageNo, int pageSize, String qualification){

    a = object.getClass();
    Integer count = countObject();
    Page page = new Page(pageNo, pageSize, count);
    List list = new ArrayList();
    Method[] m = a.getDeclaredMethods();
    String sql = "select * from ";
    sql += className + " where 1=1";

    for(Method methodName : m){
    String name = methodName.getName().toLowerCase();
    if(name.startsWith("get")){
    try {
    Object re = methodName.invoke(object, null);
    boolean types = true;
    //判断类型
    if(methodName.getReturnType().getName() == "int" && "int".equals(methodName.getReturnType().getName())){
    if((Integer)re != 0){
    types = true;
    }else
    types = false;
    }
    if(methodName.getReturnType().getName() == "java.lang.Integer" && "java.lang.Integer".equals(methodName.getReturnType().getName())){
    if((Integer)re != 0){
    types = true;
    }else
    types = false;
    }
    if((re != null) && (!("".equals(re))) && types){
    sql += " and " + name.substring(3) + MethodMap.getMap(qualification) + re;
    if("2".equals(qualification)){
    sql += "%'";
    }else{
    sql += "'";
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    System.out.println("findObject()  error!!! ");

    }
    }
    sql += " limit ";
    sql += page.getStart() + "," + page.getPageSize() + ";";
    System.out.println("------- sql: + "+ sql + "  ---------");
    try{
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    ResultSet rs = preparedStatement.executeQuery();
    Field[] f = a.getDeclaredFields();
    int leng = f.length;

    Method[] setMethods = new Method[leng];
    String[] means = new String[leng];
    int i = 0;
    for(Method methodName : m){
    String name = methodName.getName().toLowerCase();

    if(name.startsWith("set")){
    means[i] = name.substring(3);
    setMethods[i] = methodName;
    i++;
    }
    }
    while(rs.next()){
    Object obj = a.newInstance();
    for(int k = 0; k<leng;k++){
    setMethods[k].invoke(obj, rs.getObject(means[k]));
    }
    list.add(obj);
    }
    }catch(Exception e){
    e.printStackTrace();
    System.out.println("--------------findObject2 is error ------------------");
    }
    page.setData(list);
    return page;
    }

    public int countObject(){
    String objectName = a.getName();
    int num = objectName.lastIndexOf(".") + 1;
    className = objectName.substring(num).toLowerCase();
    String sql = "select count(*) from ";
    sql += className + ";";
    System.out.println("count的sql语句为: " + sql);
    Long count = null;
    try{
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    ResultSet rs = preparedStatement.executeQuery();
    while(rs.next()){
    count = rs.getLong(1);
    }
    }catch(Exception e){
    e.printStackTrace();
    System.out.println("countObject is Exception!!");
    }
    return count.intValue();
    }
    }
      

  12.   

    这个就是我对dao封装的再次修改,但是目前有个难题就是多表查询的时候,要怎么去知道两个实体中哪两个字段是有关联的,这个就是我目前想不通的地方,请大家指点,
      

  13.   

    还是一个connection打天下,只有一个人用这个吗,楼主要去看看多线程
      

  14.   

    这不是不足,而是根本不能用。这种机械地封装,只有在实际使用过程才会发现问题一大堆。拿插入和更新方法来说,能一次成功操作数据库的概率低于30%,不信楼主先跑起来看看。例如setInsert(Object object)方法:
    1、用反射来赋值,思路是对,那么主键也赋上值了?即使主键字段值是null,但拼sql时却标上了它。假如底层是自增长型主键,恺不马上报错?
    2、object中可能有final常量,不需要持久到数据库里,而按楼主的一扫而光到数据库的方式会不会报错?至少在反射时就过不去。
    3、插入一个boolean型值,底层数据库有的是存0和1,也有的是T和F,楼主是如何插入的?
    4、日期型的值用反射确保能插进去吗?
    5、......换种思路吧,做这种底层的东西,一定先要考虑设计模式和策略。
      

  15.   

    即使主键字段值是null,但拼sql时却标上了它。假如底层是自增长型主键,恺不马上报错?  主键是自增长型,即使是插入null,也不会出错,但是date型,我没去判断,谢谢你的提醒,
      

  16.   

    对于final,我真的是没考虑过,谢谢,我要考虑进去
      

  17.   

    POJO 类的属性并不是通过反射字段得来的,是通过 java.beans.Introspector 内省类获得 BeanInfo 对象,再得到 ProperyDescript 得来的。
      

  18.   

    你这个 DAO 问题有很多很多private static Connection connection = null;这句就有问题