|
1 | 1 | package databaseconnector.impl; |
2 | 2 |
|
| 3 | +import java.io.ByteArrayInputStream; |
3 | 4 | import java.sql.Connection; |
4 | 5 | import java.sql.PreparedStatement; |
5 | 6 | import java.sql.ResultSet; |
6 | 7 | import java.sql.SQLException; |
7 | 8 | import java.util.Map; |
| 9 | +import java.util.Optional; |
| 10 | +import java.util.function.BiConsumer; |
8 | 11 | import java.util.function.Function; |
9 | | -import java.util.stream.Collectors; |
| 12 | +import java.util.function.Supplier; |
10 | 13 | import java.util.stream.Stream; |
11 | 14 |
|
12 | | -import org.json.JSONArray; |
13 | | -import org.json.JSONObject; |
14 | | - |
| 15 | +import com.mendix.core.objectmanagement.member.MendixHashString; |
15 | 16 | import com.mendix.logging.ILogNode; |
16 | 17 | import com.mendix.systemwideinterfaces.core.IContext; |
17 | 18 | import com.mendix.systemwideinterfaces.core.IMendixObject; |
| 19 | +import com.mendix.systemwideinterfaces.core.meta.IMetaObject; |
| 20 | +import com.mendix.systemwideinterfaces.core.meta.IMetaPrimitive.PrimitiveType; |
18 | 21 |
|
19 | 22 | import databaseconnector.interfaces.ConnectionManager; |
20 | 23 | import databaseconnector.interfaces.ObjectInstantiator; |
21 | 24 |
|
| 25 | +/** |
| 26 | + * JdbcConnector implements the execute query (and execute statement) functionality, and returns a {@link Stream} of {@link IMendixObject}s. |
| 27 | + */ |
22 | 28 | public class JdbcConnector { |
23 | 29 | private final ILogNode logNode; |
24 | | - private ObjectInstantiator objectInstantiator; |
25 | | - private ConnectionManager connectionManager; |
| 30 | + private final ObjectInstantiator objectInstantiator; |
| 31 | + private final ConnectionManager connectionManager; |
26 | 32 |
|
27 | | - public JdbcConnector(final ILogNode logNode, ObjectInstantiator objectInstantiator, ConnectionManager connectionManager) { |
| 33 | + public JdbcConnector(final ILogNode logNode, final ObjectInstantiator objectInstantiator, final ConnectionManager connectionManager) { |
28 | 34 | this.logNode = logNode; |
29 | 35 | this.objectInstantiator = objectInstantiator; |
30 | 36 | this.connectionManager = connectionManager; |
31 | 37 | } |
32 | 38 |
|
33 | | - public JdbcConnector(ILogNode logNode) { |
| 39 | + public JdbcConnector(final ILogNode logNode) { |
34 | 40 | this(logNode, new ObjectInstantiatorImpl(), ConnectionManagerSingleton.getInstance()); |
35 | 41 | } |
36 | 42 |
|
37 | | - public Stream<IMendixObject> executeQuery(String jdbcUrl, String userName, String password, String entityName, String sql, |
38 | | - IContext context) throws SQLException { |
39 | | - Function<Map<String, Object>, IMendixObject> toMendixObject = columns -> { |
| 43 | + public Stream<IMendixObject> executeQuery(final String jdbcUrl, final String userName, final String password, final IMetaObject metaObject, final String sql, |
| 44 | + final IContext context) throws SQLException { |
| 45 | + String entityName = metaObject.getName(); |
| 46 | + |
| 47 | + Function<Map<String, Optional<Object>>, IMendixObject> toMendixObject = columns -> { |
40 | 48 | IMendixObject obj = objectInstantiator.instantiate(context, entityName); |
41 | | - columns.forEach((n, v) -> obj.setValue(context, n, v)); |
42 | | - logNode.info("obj: " + obj); |
| 49 | + |
| 50 | + BiConsumer<String, Optional<Object>> setMemberValue = (name, value) -> { |
| 51 | + PrimitiveType type = metaObject.getMetaPrimitive(name).getType(); |
| 52 | + // convert to suitable value (different for Binary type) |
| 53 | + Function<Object, Object> toSuitableValue = toSuitableValue(type); |
| 54 | + // for Boolean type, convert null to false |
| 55 | + Supplier<Object> defaultValue = () -> type == PrimitiveType.Boolean ? Boolean.FALSE : null; |
| 56 | + // apply two functions declared above |
| 57 | + Object convertedValue = value.map(toSuitableValue).orElseGet(defaultValue); |
| 58 | + // update object with converted value |
| 59 | + if (type == PrimitiveType.HashString) |
| 60 | + ((MendixHashString) obj.getMember(context, name)).setInitialHash((String) convertedValue); |
| 61 | + else |
| 62 | + obj.setValue(context, name, convertedValue); |
| 63 | + }; |
| 64 | + |
| 65 | + columns.forEach(setMemberValue); |
| 66 | + logNode.trace("Instantiated object: " + obj); |
43 | 67 | return obj; |
44 | 68 | }; |
45 | 69 |
|
46 | | - Stream<Map<String,Object>> stream = executeQuery(jdbcUrl, userName, password, sql); |
47 | | - |
48 | | - return stream.map(toMendixObject); |
| 70 | + return executeQuery(jdbcUrl, userName, password, metaObject, sql).map(toMendixObject); |
49 | 71 | } |
50 | 72 |
|
51 | | - public String executeQueryToJson(String jdbcUrl, String userName, String password, String sql, IContext context) throws SQLException { |
52 | | - Stream<Map<String, Object>> stream = executeQuery(jdbcUrl, userName, password, sql); |
53 | | - Stream<JSONObject> jsonObjects = stream.map(JSONObject::new); |
54 | | - |
55 | | - return new JSONArray(jsonObjects.collect(Collectors.toList())).toString(); |
| 73 | + private Function<Object, Object> toSuitableValue(final PrimitiveType type) { |
| 74 | + return v -> type == PrimitiveType.Binary ? new ByteArrayInputStream((byte[]) v) : v; |
56 | 75 | } |
57 | 76 |
|
58 | | - public Stream<Map<String, Object>> executeQuery(String jdbcUrl, String userName, String password, String sql) throws SQLException { |
59 | | - logNode.info(String.format("executeQuery: %s, %s, %s", jdbcUrl, userName, sql)); |
| 77 | + private Stream<Map<String, Optional<Object>>> executeQuery(final String jdbcUrl, final String userName, final String password, final IMetaObject metaObject, final String sql) throws SQLException { |
| 78 | + logNode.trace(String.format("executeQuery: %s, %s, %s", jdbcUrl, userName, sql)); |
60 | 79 |
|
61 | 80 | try (Connection connection = connectionManager.getConnection(jdbcUrl, userName, password); |
62 | 81 | PreparedStatement preparedStatement = connection.prepareStatement(sql); |
63 | 82 | ResultSet resultSet = preparedStatement.executeQuery()) { |
64 | | - ResultSetReader resultSetReader = new ResultSetReader(resultSet); |
| 83 | + ResultSetReader resultSetReader = new ResultSetReader(resultSet, metaObject); |
65 | 84 |
|
66 | 85 | return resultSetReader.readAll().stream(); |
67 | 86 | } |
68 | 87 | } |
69 | 88 |
|
70 | | - public long executeStatement(String jdbcUrl, String userName, String password, String sql) throws SQLException { |
71 | | - logNode.info(String.format("executeStatement: %s, %s, %s", jdbcUrl, userName, sql)); |
| 89 | + public long executeStatement(final String jdbcUrl, final String userName, final String password, final String sql) throws SQLException { |
| 90 | + logNode.trace(String.format("executeStatement: %s, %s, %s", jdbcUrl, userName, sql)); |
72 | 91 |
|
73 | 92 | try (Connection connection = connectionManager.getConnection(jdbcUrl, userName, password); |
74 | 93 | PreparedStatement preparedStatement = connection.prepareStatement(sql)) { |
|
0 commit comments