jdbc中查找条件动态化

一般一个select语句的查找条件具有不确定性,如果单纯的只是把查找条件本身当做参数放入查找函数中,就不具有灵活性,如下:

public Goddess queryOne(Integer id) throws SQLException {
        Goddess g=null;
        Connection conn=DBUtil.getConn();
        String sql=""+
                    " select * from imooc_goddess"+
                    " where id=?";
        PreparedStatement ptmt=conn.prepareStatement(sql);
        ptmt.setInt(1, id);
        ResultSet rs=ptmt.executeQuery();
        while(rs.next())
        {
            g=new Goddess();
            g.setId(rs.getInt("id"));
            g.setUser_name(rs.getString("user_name"));
            g.setSex(rs.getInt("sex"));
            g.setAge(rs.getInt("age"));
            g.setBirthday(rs.getDate("birthday"));
            g.setEmail(rs.getString("email"));
            g.setMobile(rs.getString("mobile"));
            g.setCreate_date(rs.getDate("create_date"));
            g.setCreate_user(rs.getString("create_user"));
            g.setUpdate_date(rs.getDate("update_date"));
            g.setUpdate_user(rs.getString("update_user"));
            g.setIsdel(rs.getInt("isdel")); 
        }
        return g;
    }

这里只是把一个条件id当做查找条件作为形参,但是事实情况可能包含很多查找条件,这时考虑可以用List

public List<Goddess> query(List<Map<String,Object>> params) throws SQLException{
        Goddess g=null;
        List<Goddess> gs = new ArrayList<Goddess>();
        Connection conn=DBUtil.getConn();
        StringBuilder sb=new StringBuilder();
        sb.append("select * from imooc_goddess where 1=1");
        if(params!=null && params.size()>0)
        {
            for(int i=0;i<params.size();i++)
            {
                Map<String,Object> tmp=params.get(i);
                sb.append(" and "+tmp.get("name")+" "+tmp.get("rea")+" "+tmp.get("value"));
            }
        }
        PreparedStatement ptmt=conn.prepareStatement(sb.toString());
        ResultSet rs=ptmt.executeQuery();
        while(rs.next())
        {
            g=new Goddess();
            g.setId(rs.getInt("id"));
            g.setUser_name(rs.getString("user_name"));
            g.setSex(rs.getInt("sex"));
            g.setAge(rs.getInt("age"));
            g.setBirthday(rs.getDate("birthday"));
            g.setEmail(rs.getString("email"));
            g.setMobile(rs.getString("mobile"));
            g.setCreate_date(rs.getDate("create_date"));
            g.setCreate_user(rs.getString("create_user"));
            g.setUpdate_date(rs.getDate("update_date"));
            g.setUpdate_user(rs.getString("update_user"));
            g.setIsdel(rs.getInt("isdel")); 
            gs.add(g);
        }
        return gs;      
    }

如果具有以下数据表imooc_goddess:
这里写图片描述
具体测试的时候比如 select * from imooc_goddess where user_name like “’%程%’” and sex=1,代码如下:

public static void main(String[] args) throws Exception {
        GoddessDao dao=new GoddessDao();
        List<Goddess> gs=new ArrayList<Goddess>();
        Goddess g=null;
        List<Map<String,Object>> params=new ArrayList<Map<String,Object>>();
        Map<String,Object> param=new HashMap<String,Object>();
        param.put("name", "sex");
        param.put("rea","=");
        param.put("value", 1);
        params.add(param);
        param=new HashMap<String,Object>();
        param.put("name", "user_name");
        param.put("rea", "like");
        param.put("value", "'%程%'");
        params.add(param);
        gs=dao.query(params);
        for(Goddess gg:gs)
        {
            System.out.println(gg.toString());
        }
    }

输出结果如下:
Goddess [id=12, user_name=程秋平, sex=1, age=20, birthday=2017-02-21, email=Viviencheng@outlook.com, mobile=15527128967, create_user=Admin, update_user=Admin, create_date=2017-02-21, update_date=2017-02-21, isdel=1]

另外一个技巧:
如果查询条件中间不用连接词and而是用or,那么就应该把sb的初始字符串的“1=1”换成”1=0”,并且在后面的连接中用”or”:

sb.append("select * from imooc_goddess where 1=0");
        if(params!=null && params.size()>0)
        {
            for(int i=0;i<params.size();i++)
            {
                Map<String,Object> tmp=params.get(i);
                sb.append(" or "+tmp.get("name")+" "+tmp.get("rea")+" "+tmp.get("value"));
            }
        }
### 使用 Sharding-JDBC 按照月份进行动态分表 #### 配置环境与依赖 确保使用的 Sharding-JDBC 版本与数据库兼容,并正确配置连接参数和分库分表规则[^2]。在 `pom.xml` 文件中引入必要的 Maven 依赖: ```xml <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>${shardingjdbc.version}</version> </dependency> ``` #### 数据源配置 定义数据源以及分片策略,在 Spring Boot 中可以通过 YAML 或者 properties 文件完成配置工作。 ```yaml spring: shardingsphere: datasource: names: ds_0,ds_1 ds_0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/db_name?serverTimezone=UTC&useSSL=false username: root password: pwd ds_1: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3307/db_name?serverTimezone=UTC&useSSL=false username: root password: pwd ``` #### 动态分表逻辑设计 对于按月创建的新表,可以采用时间字段作为分片键,通过自定义算法实现基于当前日期自动切换目标表格的功能。具体来说,可以在应用启动时加载现有表结构信息并定期刷新缓存;当有新请求到来时计算出对应的目标表名再执行 SQL 查询操作。 #### 自定义分片算法 编写 Java 类继承 AbstractShardingKeyGenerator 和 StandardShardingAlgorithm 来定制化分片规则。这里提供了一个简单的例子用于说明如何根据年份加月份生成不同的物理表名称: ```java public class MonthBasedTableShardingAlgorithm extends StandardShardingAlgorithm<String> { @Override protected Collection<String> doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) { String logicTableName = shardingValue.getLogicTableName(); Date date = (Date) shardingValue.getValue(); // 假设传入的是 java.util.Date 对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); Calendar cal = Calendar.getInstance(); cal.setTime(date); List<String> result = new ArrayList<>(); for (String each : availableTargetNames) { if (each.startsWith(logicTableName)) { try { int tableYearMonth = Integer.parseInt(each.substring(logicTableName.length())); int targetYearMonth = Integer.parseInt(sdf.format(cal.getTime()).substring(0, 6)); if (tableYearMonth == targetYearMonth) { result.add(each); } } catch (NumberFormatException ignored) {} } } return result; } } ``` 此代码片段实现了基于给定日期查找匹配的物理表功能。实际开发过程中还需要考虑更多边界情况,比如闰秒、夏令时等因素的影响。 #### 表结构初始化脚本 考虑到每月都会新增一张表,建议预先准备好建表语句模板,运行定时任务于月初创建下个月所需的空表。例如 MySQL 下面这样的 DDL 可以用来建立 alarm_history_yyyymm 形式的表: ```sql CREATE TABLE IF NOT EXISTS ${logic_table}_${year}${month} ( id BIGINT AUTO_INCREMENT PRIMARY KEY, node_id INT NOT NULL COMMENT '节点ID', metric_value DOUBLE DEFAULT NULL COMMENT '指标数值', collect_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '采集时间' ) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; ``` 其中 `${logic_table}` 是业务逻辑层中的统一表名占位符,`${year}`, `${month}` 则由程序填充具体的四位数表示法的年份和两位数表示法的月份。 #### 应用部署优化 为了提升部署效率和可维护性,推荐使用容器化技术如 Docker 进行打包发布。这不仅简化了运维流程还增强了系统的移植性和稳定性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值