Tengo un problema al configurar una conexión de solo lectura con una base de datos PostgreSQL usando JDBC.
Estoy creando una aplicación que carga consultas para ejecutar desde un archivo, y quiero ejecutar solo consultas SELECT (solo lectura). Establecer permisos en los usuarios que ejecutarán la aplicación no es una opción, por lo que establecer permisos a nivel de código a través del método Connection.setReadOnly(boolean) fue la única opción que se me ocurrió.
Ahora el problema es que probé mi aplicación para una consulta de inserción y eliminación y se ejecutan normalmente, por lo que mi solución no funciona.
¿Algún consejo sobre cómo resolver el problema?
Aquí debajo del fragmento de código simple que estoy probando:
public class Test{ public static void main(String[] args) { connectAndExecute(); } public static void connectAndExecute() { try { Class.forName("org.postgresql.Driver"); } catch (ClassNotFoundException e1) { e1.printStackTrace(); return; } Connection connection; String connString = "jdbc:postgresql://localhost:5432/testdb"; try { connection = DriverManager.getConnection(connString, "user", "password"); } catch (SQLException e) { e.printStackTrace(); return; } try { connection.setReadOnly(true); connection.createStatement().execute("delete from testtable"); // connection.createStatement().execute("insert intotesttable(testfield1)values('test')"); } catch (SQLException e) { e.printStackTrace(); } }y este es el controlador JDBC que estoy usando
<groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.10</version>Versión PostgreSQL: 11.6
El problema parece estar relacionado con un error del controlador.
Estas dos soluciones trabajaron para mí:
ejecutando primero el comando sql
SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLYdeshabilitar la confirmación automática hace que la llamada setReadOnly sea efectiva
Connection.setAutoCommit(false); Connection.setReadOnly(true);Solo para ser claros: la especificación para el método setReadOnly no tiene como objetivo evitar que se actualice la base de datos.
Como dice la API de Java:
https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#setReadOnly-boolean-
"Pone esta conexión en modo de solo lectura como una sugerencia para que el controlador habilite las optimizaciones de la base de datos"
Por lo tanto, no es una buena idea confiar en este método para asegurar cualquier cosa relacionada con la necesidad de tener transacciones de solo lectura :)