Interface DataStorage
- Since:
- Mendix 7
-
Method Summary
Modifier and TypeMethodDescription<R> R
executeWithConnection
(IContext context, Function<Connection, R> function) The only difference is that this method executes the function on the current connection of the given context, allowing function execution to be part of the current transaction.<R> R
executeWithConnection
(Function<Connection, R> function) Executes the given function and returns its result.
-
Method Details
-
executeWithConnection
Executes the given function and returns its result. When the function is executed, an open database connection will automatically be given as its first argument. This connection will be automatically closed afterwards.The function being passed must not throw checked exceptions. If you want to throw an exception, for example to rollback a microflow action, you must throw an unchecked exception, like a
java.lang.RuntimeException
.Note that this method is only provided for convenience, for example to enable execution of database-specific SQL SELECT statements, or calling stored procedures created in the same database (schema), with a direct connection to the Mendix database.
DISCLAIMER
ANY USAGE OF THIS METHOD ON THE MENDIX DATABASE WITH DATA MUTATING SQL STATEMENTS LIKE (BUT NOT LIMITED TO) DELETE AND UPDATE, OR SCHEMA MUTATING SQL STATEMENTS LIKE (BUT NOT LIMITED TO) DROP AND ALTER, IS ENTIRELY AT YOUR OWN RISK. MENDIX CANNOT GUARANTEE THE CONSISTENCY OF THE MENDIX DATABASE DATA OR SCHEMA UNDER SUCH USAGE.
One should be especially careful with the Mendix administration tables in the MENDIXSYSTEM$ and SYSTEM$ module namespaces. Please be aware that the existence of Mendix administration tables, and the naming conventions in the database, are a Mendix-internal implementation detail, and are potentially subject to change between different Mendix versions.
To avoid tight coupling between your queries and database-specific names, please use Mendix Core API methods with Mendix Core Meta classes to retrieve database-specific table and column names:
Core.getDatabaseTableName(IMetaObject)
Core.getDatabaseTableName(IMetaAssociation)
Core.getDatabaseColumnName(IMetaPrimitive)
Core.getDatabaseChildColumnName(IMetaAssociation)
Core.getDatabaseParentColumnName(IMetaAssociation)
References to table and column names from within stored procedures in the database might become invalid after a change in the Mendix domain model has been synchronized with the database.
Furthermore, executing the SQL INSERT statement on tables in the Mendix database should be avoided. Mendix creates a special unique ID for each data row in the table, where its Long data type actually has a specialized Mendix-internal representation. Inserting one's own data row in a table with a custom ID might lead to unspecified or undesired external behavior, like not being able to retrieve such data rows in a data grid.
Please be advised that the automated backup of the Mendix cloud database (PostgreSQL) is only done for the PUBLIC schema. By using this method, any (meta)data that is stored in another schema might potentially be lost on hardware failure.
Code examples
Basic examples
Example without parameters:
private Report generate(Connection connection) { Report report = new Report(); try (Statement statement = connection.createStatement()) { ... report.addRow(..); } catch (SQLException e) { // handle exception } return report; } public Report generateReport() { return Core.dataStorage().executeWithConnection(this::generate); }
Example with parameters:
private Function<Connection, Report> createReportOnConnection(String name, LocalDate start, LocalDate end) { return connection -> { Report report = new Report(); try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { // do something with the result set and fill the report } catch (SQLException e) { // handle exception } return report; }; } public Report createReport(String name, LocalDate start, LocalDate end) { return Core.dataStorage().executeWithConnection(createReportOnConnection(name, start, end)); }
Examples with checked exceptions
In this example, the exception is caught and wrapped in a
java.lang.RuntimeException
:private Report generate(Connection connection) { Report report = new Report(); try (Statement statement = connection.createStatement()) { ... report.addRow(..); } catch (SQLException e) { throw new RuntimeException(e); } return report; } public Report generateReport() { return Core.dataStorage().executeWithConnection(this::generate); }
In this example, we make use of the Durian library, to wrap checked exceptions more easily:
private Report generate(Connection connection) throws Exception { Report report = new Report(); try (Statement statement = connection.createStatement()) { ... report.addRow(..); } // do not handle the exception here return report; } public Report generateReport() { return Core.dataStorage().executeWithConnection(Errors.rethrow().wrap(this::generate)); }
Either
.- Parameters:
function
- the function to execute with a database connection as argument- Returns:
- the result of the given function.
-
executeWithConnection
The only difference is that this method executes the function on the current connection of the given context, allowing function execution to be part of the current transaction. This connection will not be automatically closed afterwards.- Parameters:
context
- the context to execute this function onfunction
- the function to execute with a database connection as argument- Returns:
- the result of the given function
- Since:
- 7.6
- See Also:
-