Во-первых, ответ Джона о том, что вы должны использовать самое очевидное решение до тех пор, пока производительность не станет проблемой, безусловно, является правильным подходом в целом.
Я не думаю, что ваши проблемы с производительностью неуместны. Я, конечно, видел, как предварительно скомпилированные сложные операторы резко терпели неудачу в масштабе производительности (в MS-SQL 2000). Причина в том, что оператор был настолько сложным, что в нем было несколько возможных путей выполнения в зависимости от параметров, но компиляция блокировала один для одного набора параметров, а следующий набор параметров был слишком медленным, тогда как перекомпиляция приводила бы к пересчету план выполнения больше подходит для другого набора параметров.
Но это беспокойство очень далеко, пока вы не увидите его на практике.
Основная проблема здесь заключается в том, что экранирование параметров зависит от конкретной базы данных, поэтому, если драйвер JDBC для вашей базы данных не даст вам чего-то нестандартного для этого (весьма маловероятно), вам понадобится другая библиотека или другая механизм экранирования, который очень специфичен для этой базы данных.
Судя по формулировке вашего вопроса, это не означает, что ваши проблемы с производительностью еще не достигли цели найти (или разработать) такое решение.
Следует также отметить, что хотя драйверы JDBC могут не все вести себя таким образом, технически в соответствии со спецификацией предварительная компиляция должна кэшироваться в объекте PreparedStatement, и если вы выбрасываете это и каждый раз получаете новый PreparedStatement, на самом деле он не должен ничего кешировать, поэтому вся проблема может быть немой, и ее нужно будет исследовать для конкретного драйвера JDBC.
Из спецификации:
Оператор SQL с параметрами IN или без них можно предварительно скомпилировать и сохранить в объекте PreparedStatement. Этот объект затем может быть использован для эффективного выполнения этого оператора несколько раз.