把剩下的功能都完成了,代码太长,不全贴,就贴出最复杂的更新功能,自己感觉逻辑上特别啰嗦,但当局者迷自己也想不出怎样优化,贴出来看看有没有好的建议

来源:2-9 JDBC实战---搭建视图层(下)

红袖侍读

2016-07-01 12:52

public void updateGoddess(Goddess goddess) throws SQLException{
        Connection conn = DBUtil.getConnection();    

        StringBuilder sql=new StringBuilder();
        sql.append("update femalegod set ");
        //这个comFlag标记用来确定是否要在拼接语句时加逗号
        boolean comFlag=false;
        
        //如果本属性非空,后面的属性拼接时必然要加逗号,所以comFlag赋值为true
        if (goddess.getUserName()!=null){
            sql.append("username=?");
            comFlag=true;
        }
        
        //如果本属性非空,且comFlag为false,说明本属性为set关键字后第一个设置,则前面无需加逗号,
        //同时由于本属性非空,说明后面如果有要拼接的属性,必须有逗号,所以设置comFlag为true
        if (goddess.getAge()!=null){
            if (comFlag)        
                sql.append(",age=?");//comFlag为真,说明前面已有待更新的属性,因此要在最前面加逗号
            else{
                sql.append("age=?");//comFlag为假,前面还没有待更新属性,本属性为第一个待更新的,无需在前面加逗号
                comFlag=true;       //如果后面还有属性要更新,那个属性前需要加逗号,因此在这里设置comFlag为true
            }
        }
            
        if (goddess.getBirthday()!=null){
            if (comFlag)
                sql.append(",birthday=?");
            else{
                sql.append("birthday=?");
                comFlag=true;
            }
        }
        if (goddess.getEmail()!=null){
            if (comFlag)
                sql.append(",email=?");
            else{
                sql.append("email=?");
                comFlag=true;
            }
        }
        if (goddess.getMobile()!=null){
            if (comFlag)
                sql.append(",mobile=? ");
        }
            
        sql.append(" where id=?");
        
        System.out.println(sql.toString());
        PreparedStatement ps=conn.prepareStatement(sql.toString());
        
        //i为参数索引值
        int i=0;
        
        //为前面的sql语句里的?号取对应的属性值,如果属性为空,则不需要更新,跳过,否则,提取属性值
        if(goddess.getUserName()!=null)
            ps.setString(++i, goddess.getUserName());
        if(goddess.getAge()!=null)
            ps.setInt(++i, goddess.getAge());
        if(goddess.getBirthday()!=null)
            ps.setDate(++i, new Date(goddess.getBirthday().getTime()));
        if(goddess.getEmail()!=null)
            ps.setString(++i, goddess.getEmail());
        if(goddess.getMobile()!=null)
            ps.setString(++i, goddess.getMobile());
        ps.setInt(++i, goddess.getID());
        
        ps.execute();
        ps.close();
    }


写回答 关注

9回答

  • 红袖侍读
    2016-08-07 01:05:12

    上面“不然变成where 1=1 username like "xiao%"就出错了”忘了加注释符,复杂查询我只做了如上测试,因为时间关系(后面有太多课程要学,不想在一个项目上纠缠太久),没有在视图层的代码里做相应改动以便用户可以在前台输入复杂多个查询,有兴趣有时间的童鞋可以试试,有问题大家再来一起交流讨论

  • 红袖侍读
    2016-08-07 00:51:59

    根据姓名或手机查询女神,这个方法我本来根据老师上课的要求做了点扩充,可以根据多个条件的与或进行查询,课程看到最后发现项目的要求其实很简单,只按单个条件查询,而且限定在手机或姓名,既然前面复杂条件能查询到,简单查询当然更可以,所以我也没改这部分,功能一样能实现。

    public List<Goddess> queryGoddessList(List<Map<String,Object>> params) throws SQLException{
            Connection conn = DBUtil.getConnection();        
            List<Goddess> gs = new ArrayList<Goddess>();
            Goddess g = null;
            
            StringBuffer sb = new StringBuffer();
            sb.append("select * from femalegod where 1=1"); //设置 1=1这个永远为真的条件是为了和下面的田间查询做拼接
            
            if(params!=null && params.size()>0){ //判断查询参数列表非空
                for(int i=0;i<params.size();i++){
                    Map<String,Object> param = params.get(i);//依次取出查询参数
                    sb.append(" "+param.get("connector")+" "+param.get("name")+" "+param.get("rela")+" "+"'"+param.get("value")+"'");
                }//对参数做拼接,connector存放连接符&&或||,name存放查询字段名,rela存放关系符=,>,等等,value存放字段值
            }
            
            System.out.println(sb.toString()); //输出拼接后的sql查询语句便于调试纠错
            
            /**
             * 以下部分为常规操作,对查询得到的结果集依次放入对象
             * 并添加进list,返回
             */
            PreparedStatement ps=conn.prepareStatement(sb.toString());
            ResultSet rs=ps.executeQuery();
            while(rs.next()){
                g = new Goddess();
                g.setID(rs.getInt("ID"));
                g.setUserName(rs.getString("username"));
                g.setAge(rs.getInt("age"));
                g.setBirthday(rs.getDate("birthday"));
                g.setEmail(rs.getString("email"));
                g.setMobile(rs.getString("mobile"));
                gs.add(g);
            }
    //        
            return gs;
        }
    如果也想试试复杂查询的效果,我这里写了个测试例子,根据三个条件姓名,年龄,及生日查询
    
    public static void main(String[] args) throws SQLException {
            
            GoddessMethod gsMethod = new GoddessMethod();
            
            List<Map<String,Object>> params = new ArrayList<Map<String,Object>>();
            //设计的查询例子:username like "xiao%" or age=20 or birthday=1994-01-01
            
            //第一套参数: and username like "xiao%", 最前面放一个and是为了跟查询方法里的where 1=1 拼接上
            不然变成where 1=1 username like "xiao%"就出错了
            Map<String,Object> param = new HashMap<String,Object>();
            param.put("connector", "and");
            param.put("name", "username");
            param.put("rela", "like");
            param.put("value", "'xiao%'");        
            params.add(param);
    
            //第二套参数: age = 20
            param = new HashMap<String,Object>();
            param.put("connector", "or");
            param.put("name", "age");
            param.put("rela", "=");
            param.put("value", "20");
            params.add(param);
            
            //第三套参数: birthday = 1994-01-01
            param = new HashMap<String,Object>();
            param.put("connector", "or");
            param.put("name", "birthday");
            param.put("rela", "=");
            param.put("value", "to_date('1994-01-01','yyyy-mm-dd')");
            params.add(param);
            
            //输出params对象里存放的参数,查看是否正确
            for (int i=0;i<params.size();i++){
                System.out.println(params.get(i).get("connector")+" "+params.get(i).get("name")+" "+params.get(i).get("rela")+" "+params.get(i).get("value"));
            }
            
            //调用查询方法,并输出
            List<Goddess> gs = gsMethod.queryGoddessList(params);
            for(Goddess g: gs){
                System.out.println(g.getUserName()+","+g.getAge());
            }


  • 蔬菜果
    2016-07-22 15:24:10

    你的根据姓名和手机号查询女神部分是怎么写的????

    红袖侍读

    代码贴在下面

    2016-08-07 00:28:05

    共 1 条回复 >

  • 书子
    2016-07-19 11:22:59

    看起来好繁琐。

  • 小周先森57410
    2016-07-02 14:32:14

    求教返回主菜单

    红袖侍读

    按正常逻辑,你如果维持在某一功能里靠的是previous这个变量对不对,如果要返回主菜单,把previous清空设回null就行了。但其实按本作业老师的这种写法,所有的条件都是或的关系,你如果把返回主菜单的那个if判断语句写在最前面,任何时候只要输入B就能进入主菜单了,甚至都不需要判断previous

    2016-07-02 23:08:14

    共 1 条回复 >

  • 红袖侍读
    2016-07-02 05:52:39

    实际开发中,要修改对象,肯定是要读到一个对象再修改,所以我觉得可以不用做判断的

    =================================

    你的意思是假如我只更新一个属性,譬如

    update 某表 set 属性=? where 条件

    但在这种情况下我也得把SQL语句写全了

    update 某表 set 属性1=?,属性2=?,属性3=?。。。。 where 条件

    即使大部分属性不用更新,也得拿原来的值再赋一遍?这当然也算个办法,只是我本想着有没有更妙的写法,可以写得比较符合实际,不用加一堆没必要的赋值,就像老师的课程里提到的where 1=1那个小技巧。现在看来是没有这种技巧,要么就很笨很啰嗦像我这样挨个判断挨个拼接,要么就不管三七二十一,所有属性都更新一遍,即使值不变?其实后一种情况这里处理起来也很麻烦,如果我从控制台得到一个更新属性,其余都为空的话,我是不是还得用一个select语句找到对应的这条记录,把它的属性值全部取出来,除了要更新的那个属性,其余属性都得原样填到上一个update对应的问号里去?

  • Janeil
    2016-07-02 00:01:32

    实际开发中,要修改对象,肯定是要读到一个对象再修改,所以我觉得可以不用做判断的

    红袖侍读

    我的回复有点长,小回复框写不下,我放在下面了

    2016-07-02 05:50:33

    共 1 条回复 >

  • Janeil
    2016-07-01 23:58:58

    /**

    * 修改

    * @throws SQLException

    */

    public void updateGoddess(Goddess goddess) throws SQLException {

    String sql = " update imooc_goddess "

    + " set user_name=?,sex=?,age=?,birthday=?,email=?,mobile=?,"

    + " update_user=?,update_date=current_date(),isdel=? where id=?";

    PreparedStatement ptmt = conn.prepareStatement(sql);

    ptmt.setString(1, goddess.getUser_uame());

    ptmt.setInt(2, goddess.getSex());

    ptmt.setInt(3, goddess.getAge());

    ptmt.setDate(4, new Date(goddess.getBirthday().getTime()));

    ptmt.setString(5, goddess.getEmail());

    ptmt.setString(6, goddess.getMobile());

    ptmt.setString(7, goddess.getUpdate_user());

    ptmt.setInt(8, goddess.getIsdel());

    ptmt.setInt(9, goddess.getId());

    ptmt.execute();

    }

    拿到要修改的对象,再把对要修改的属性象重新赋值,再保存进去,直接操作对象。(这里只是所有属性都有值的情况下,有NULL值的时候要自己做验证判断)

  • 再见残月
    2016-07-01 18:54:08

    不建议这样写,太乱。

    建议把各个功能分别封装在不同方法中,在主程序中去调用各个方法去实现对应功能

    public void operatlin_query() throws Exception{//查询所有

    public void operatlin_get(Integer id) throws SQLException{//查询单个

    public void operatlin_add() throws Exception{//添加

    public void operatlin_update() throws Exception{//更新

    public void operatlin_delete() throws Exception{//删除

    public void operatlin_search() throws Exception{//根据姓名、手机号来查询

    while(true){

        if(){

               //“if”判断输入主菜单命令,在语句中直接调用对应方法

        } else if(){


        }else if(){


        }..............

    }


    这样写看起来有条理些,便于以后优化

    红袖侍读

    擦汗,我就是把各功能分拆在不同函数里写的啊,上面贴的仅仅是更新功能|||||

    2016-07-01 22:55:20

    共 1 条回复 >

JDBC之 “ 对岸的女孩看过来”

一起领略JDBC的奥秘,为进一步学习集成框架打下良好的基础

99327 学习 · 856 问题

查看课程

相似问题