美文网首页程序员Android亮书房
【实践记录】Java操作MySQL数据库——不定条件参数查询

【实践记录】Java操作MySQL数据库——不定条件参数查询

作者: LAVAGUE | 来源:发表于2016-08-18 23:11 被阅读4473次

    引入

    在数据库中,经常要实现查询操作,而且查询条件是不断根据实际情况动态变化的,以简书用户为例。假设一个简书用户有以下参数:用户名、个人简介、关注人数、粉丝人数、文章数、字数、收获喜欢数。如果我们的查询条件是用户名为某个值这一个条件、又或者用户名为某个值和关注人数在某一区间这两个条件。通过Java操作的话,我们不可能每种情况都写一个查询方法,最有效的方法应该是:只写一个方法,让他自己检测参数个数,获取条件参数,实现对应的数据库操作。那么该如何实现呢?


    知识点归纳(方法步骤)

    1.数据库设计

    为了方便,直接使用Navicat for MySQL来创建数据表
    要点:
    (1)、设置默认字符集为 utf8
    (2)、字段类型:char类型长度固定、varchar类型长度随内容变化

    CREATE TABLE users(
        u_id int NOT NULL AUTO_INCREMENT,
        u_name char(20) NOT NULL UNIQUE,
        u_introduce char(50) NOT NULL,
        u_num_focus bigint NOT NULL,
        u_num_fans bigint NOT NULL,
        u_num_ariticles bigint NOT NULL,
        u_num_words bigint NOT NULL,
        u_num_like bigint NOT NULL,
        PRIMARY KEY(u_id)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    随意添加数据后,数据库如图:

    数据库示例.png
    2.根据数据库编写Users类

    要点:
    (1)、MyEclipse中菜单栏 Source 中选项 Generate Getters and Setters 可以自动创建set()、get()方法。

    /*
     *     省略了set()、get()方法
     */
    public class Users {
        private int Id;
        private String name;
        private String introduce;
        private long focusNum;
        private long fansNum;
        private long ArticlesNum;
        private long wordsNum;
        private long likeNum;
    }
    
    3.编写连接、关闭数据库的util工具类

    要点:
    (1)、Java连接MySQL数据库需要JDBC驱动:本人的为 mysql-connector-java-5.1.39-bin.jar
    (2)、Java连接MySQL数据库的连接语句记得设置字符集 useUnicode=true&characterEncoding=utf-8。(踩了坑,花了一天才解决出现的MySQL不识别中文字符问题)

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class DBUtil {
        /*
         * 获取数据库的连接
         */
        public static Connection getConnection(){
            Connection conn = null;
            try {
                conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db_jianshuuser?useUnicode=true&characterEncoding=utf-8", "root", "123456");
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return conn;
        }
        
        /*
         * 关闭数据库的连接
         */
        public static void close(Connection conn){
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    
    4.在UserDAO类中实现不定条件参数查询

    要点:
    (1)、通过Map<String,Object>存储参数条件、通过List<Map<String,Object>> 来存储多个参数条件
    (2)、代码中SQL语句通过 and 实现查询条件的交集,当然也可以通过 or实现查询条件的并集,不过拼接SQL语句写法会有不同
    (3)、SQL语句中 where 1=1 用来避免无查询条件时会出错。但如果确保有参数,其实也不用加 1=1.写法参照下文的拓展——通过 or实现查询条件的并集。

    import java.io.UnsupportedEncodingException;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import demo.pojo.Users;
    import util.DBUtil;
    
    public class UsersDAO {
        /*
         * 不定条件参数查询
         */
        public static Map<String,Object> addCondition(String str1,String str2,Object obj){
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("name",str1);
            map.put("rela",str2);
            map.put("value",obj);
            return map;
        }
        
        public static List<Users> query(List<Map<String,Object>> params) throws SQLException{
            //获取数据库连接
            Connection conn = DBUtil.getConnection();       
            List<Users> usersList = new ArrayList<Users>();
            //通过拼接构建SQL语句
            StringBuilder sb = new StringBuilder();
            sb.append("select * from users where 1=1 ");
            if(params!=null&&params.size()>0){
                for(int i = 0;i<params.size();i++){
                    Map<String,Object> map = params.get(i);
                    sb.append(" and "+map.get("name")+" "+map.get("rela")+" "+map.get("value")+" ");
                }
            }
            //执行SQL语句
            PreparedStatement ps =conn.prepareStatement(sb.toString()); 
            System.out.println(sb.toString());
            ResultSet rs = ps.executeQuery();
            //提取查询结果
            Users user = null;
            while(rs.next()){
                user = new Users();
                user.setId(rs.getInt("u_id"));
                user.setName(rs.getString("u_name"));
                user.setIntroduce(rs.getString("u_introduce"));
                user.setFocusNum(rs.getLong("u_num_focus"));
                user.setFansNum(rs.getLong("u_num_fans"));
                user.setArticlesNum(rs.getLong("u_num_ariticles"));
                user.setWordsNum(rs.getLong("u_num_words"));
                user.setLikeNum(rs.getLong("u_num_like"));
                    
                usersList.add(user);
                }
            return usersList;
        }
    }
    
    5.测试

    要点:
    (1)、通过List对象的add方法添加参数个数
    (2)、MySQL数据库中如果字段是字符类型的需要加单引号 'xxx',如 '小明'
    **示例一:

    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import demo.dao.UsersDAO;
    import demo.pojo.Users;
    
    public class Test {
        public void show(){
            List<Map<String,Object>> params = new ArrayList<Map<String,Object>>();
            params.add(UsersDAO.addCondition("u_num_fans",">","100"));
            try {
                List<Users> usersList = new ArrayList<Users>();
                usersList = UsersDAO.query(params);
                for(Users s:usersList){
                    System.out.println("Id:"+String.valueOf(s.getId()));
                    System.out.println("昵称:"+s.getName());
                    System.out.println("个人介绍:"+s.getIntroduce());
                    System.out.println("关注人数:"+String.valueOf(s.getFocusNum())+"人");
                    System.out.println("粉丝人数:"+String.valueOf(s.getFansNum())+"人");
                    System.out.println("文章数:"+String.valueOf(s.getArticlesNum())+"篇");
                    System.out.println("字数:"+String.valueOf(s.getWordsNum())+"字");
                    System.out.println("收获喜欢数:"+String.valueOf(s.getLikeNum())+"个");
                    System.out.println();
                }
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        public static void main(String[] args) {
            Test test = new Test();
            test.show();
        }
    }
    
    示例一结果.png

    示例二:
    添加代码:

    params.add(UsersDAO.addCondition("u_name","=","'小明'"));
    
    示例二结果.png

    拓展

    1.通过 or 实现查询条件的并集

    要点:
    (1)、从第二个条件参数前开始加 or

            //通过拼接构建SQL语句
            StringBuilder sb = new StringBuilder();
            sb.append("select * from users where ");
            if(params!=null&&params.size()>0){
                if(params.size()==1){
                    Map<String,Object> map = params.get(0);
                    sb.append(map.get("name")+" "+map.get("rela")+" "+map.get("value")+" ");
                }else{
                    Map<String,Object> map0 = params.get(0);
                    sb.append(map0.get("name")+" "+map0.get("rela")+" "+map0.get("value")+" ");
                    for(int i = 1;i<params.size();i++){
                        Map<String,Object> map = params.get(i);
                        sb.append(" or "+map.get("name")+" "+map.get("rela")+" "+map.get("value")+" ");
                    }
                }       
            }
    
    or条件示例结果.png

    注意事项(本次实践踩的坑)

    1.连接MySQL数据库的连接语句记得设置编码格式,与数据库默认字符集相对应。不然很容易出现中文乱码或者查询不出正确结果。如何判断是编码格式问题方法:数据库新增一条记录,字符串部分用英文代替,跑一次程序若能正常运行,则是编码格式(中文无法正常识别)出了问题。
    2.SQL注入引起的安全问题。网上评论说通过SQL语句拼接的方法容易导致SQL注入,由于没有接触过SQL注入,所以暂时无法细说。大概就是恶意SQL语句也拼接进来了吧。

    相关参考

    慕课网JDBC教程搭建模型层IV
    java编码字符集及jdbc连接数据库指定字符集
    SQL注入——百度百科

    相关文章

      网友评论

        本文标题:【实践记录】Java操作MySQL数据库——不定条件参数查询

        本文链接:https://www.haomeiwen.com/subject/ofzpsttx.html