简体   繁体   中英

PreparedStatementCallback dynamic query parameters

I have a PreparedStatementCallback in my DAO, my business requirement is to implement a JSON_SET function call (my backend is MySQL 8), so far I have done this:

SQL_Query = UPDATE MY_TABLE SET BLA_BLA=?, MY_JSON=JSON_SET('MY_JSON', ?), TIME =? WHERE KEY_1=? AND KEY_2=?

My snippet for executing this in batch:

    jdbcTemplate.execute(SQL_Query , new PreparedStatementCallback<Object>() {
                    int counter = 0, recordsUpdated = 0;
                    @Override
                    public Object doInPreparedStatement(PreparedStatement ps) throws DataAccessException {
                        try {
                            for (Entity entity : entities) {
                                if (++counter >= batchSize) {
                                    recordsUpdated += Arrays.stream(ps.executeBatch()).sum();
                                    ps.clearBatch();
                                    counter = 0;
                                }
                                try {
                                    switch (type) {
                                        case UPDATE:
                                        case PARTIAL_UPDATE:
                                            if(entity.getJsonMap() != null) {
                                                setPreparedStatementValuesForUpdate(ps, entity, type);
                                            }
                                            break;
                                        default:
                                            setPreparedStatementValues(ps, entity);
                                    }
                                    ps.addBatch();
                                } catch (JsonProcessingException e) {
                                    LOGGER.error("Error in converting JSON : {}", e.getLocalizedMessage());
                                }
                            }
                            recordsUpdated += Arrays.stream(ps.executeBatch()).sum();
                            ps.clearBatch();
                        } catch (Exception e) {
                            LOGGER.error("Error occurred : {}", e.getLocalizedMessage());
                            LOGGER.info("PS Query : {}", ps.toString());
                            e.printStackTrace();
                        }
                        return recordsUpdated;
                    }
                });
                return Integer.parseInt(insertCount == null ? "0" : insertCount.toString());


private void setPreparedStatementValuesForUpdate(PreparedStatement ps, Entity entity, TransactionType type)
                throws SQLException, JsonProcessingException {
            ps.setString(1, entity.getTime());
            if(TransactionType.PARTIAL_UPDATE.equals(type)) {
                final String dataToUpdate = StringEscapeUtils.escapeJson(getPartialJSONData(entity));
                if(StringUtils.isEmpty(dataToUpdate)) {
                    ps.setString(2, "'$.\"1\"', `JSON`->>'$.\"1\"'");
                } else {
                    ps.setString(2, dataToUpdate);
                }
            } else {
                ps.setString(2, objectMapper.writeValueAsString(entity.getDbdMeasures()));
            }
            ps.setString(3, entity.getTime());
            ps.setString(4, entity.getKey1());
            ps.setInt(5, entity.getKey2());
        }
private String getPartialJSONData(final Entity entity) {
        final StringBuilder builder = new StringBuilder();
        builder.append(String.join(",", entity.getJsonMap().entrySet().stream()
                .map(entry -> {
                    try {
                        return "'$.\"" + entry.getKey() + "\"', " + objectMapper.writeValueAsString(entry.getValue());
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                    return null;
                }).collect(Collectors.toList())));
        return builder.toString();
    }

But I receive error that incorrect number of parameters passed to JSON_SET. That is because I passed entire string as one for parameters. And preparedstatement is good for avoiding sql injection. So I need to understand a possible workaround for this, or should I change the code itself altogether. I am considering JPA and jOOQ, provided I must get partial update for JSON document.

You cannot do it this way. Your second parameter is a single string, which means you are doing the equivalent of

JSON_SET('MY_JSON', '''$."1"'', `JSON`->>''$."1"'''

which obviously isn't correct

As you need to pass three (or 5, or 7, ...) values to JSON_SET , you'll need to use two parameters:

JSON_SET('MY_JSON', ?, ?)

And set those parameters appropriately. If you need to apply different operations depending on some logic, then you should use different UPDATE statements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM