Skip to content

Commit 14f3a23

Browse files
committed
Added support for stored procedures and functions
1 parent 4c59d7a commit 14f3a23

File tree

16 files changed

+436
-127
lines changed

16 files changed

+436
-127
lines changed

.github/workflows/post-push.yml

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,6 @@ jobs:
2626
nexus_username: ${{ secrets.nexus_username }}
2727
nexus_password: ${{ secrets.nexus_password }}
2828

29-
github_deploy:
30-
name: Deploy to GitHub Packages
31-
runs-on: ubuntu-latest
32-
steps:
33-
- name: Check out Git repository
34-
uses: actions/checkout@v1
35-
36-
- name: Setup JDK 13
37-
uses: actions/setup-java@v1
38-
with:
39-
java-version: '13'
40-
41-
- name: Release to GitHub Package Registry
42-
env:
43-
github_token: ${{ secrets.GITHUB_TOKEN }}
44-
gpg_private_key: ${{ secrets.gpg_private_key }}
45-
gpg_passphrase: ${{ secrets.gpg_passphrase }}
46-
run: |
47-
mkdir -p ~/.m2
48-
echo "${gpg_private_key}" | gpg --batch --import
49-
echo "<settings><servers><server><id>github</id><username>CollinAlpert</username><password>${github_token}</password></server></servers></settings>" > ~/.m2/settings.xml
50-
mvn clean deploy -B -e -Dmaven.wagon.http.pool=false -DaltDeploymentRepository=github::default::https://maven.pkg.github.com/CollinAlpert/Java2DB -Dgpg.passphrase=${gpg_passphrase}
51-
5229
github_release:
5330
name: Create GitHub release
5431
runs-on: ubuntu-latest

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Include the Maven artifact:
2020
<dependency>
2121
<groupId>com.github.collinalpert</groupId>
2222
<artifactId>java2db</artifactId>
23-
<version>5.3.0</version>
23+
<version>5.4.0</version>
2424
</dependency>
2525
```
2626
Or include the [JAR](https://github.com/CollinAlpert/Java2DB/releases/latest) in your project.
@@ -157,6 +157,9 @@ You can also check if a table has at least one row by calling `personService.any
157157
### Duplicate value checking
158158
To check if a column's values are unique in a table, use the `hasDuplicates` method provided by the `BaseService`. It will return `true` if there is at least one duplicate value and false if all the values are unique.
159159

160+
### Programmability
161+
The `DBConnection` class offers the possibility to call a stored procedure and a function. Simply use the `callStoredProcedure` or `callFunction` method, respectively and pass in the class you would like the result mapped to. Using the `@Ignore` annotation will also work with these kinds of calls. Please make sure your class has an empty constructor.
162+
160163
### Asynchronous operations
161164
As of version 4.0 it is possible to execute all of the CRUD operations asynchronously.
162165
To use the asynchronous methods with your service classes, the individual service class should inherit from the

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.github.collinalpert</groupId>
88
<artifactId>java2db</artifactId>
9-
<version>5.3.0</version>
9+
<version>5.4.0</version>
1010
<packaging>jar</packaging>
1111

1212
<name>Java2DB</name>

src/main/java/com/github/collinalpert/java2db/database/DBConnection.java

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package com.github.collinalpert.java2db.database;
22

33
import com.github.collinalpert.java2db.exceptions.ConnectionFailedException;
4+
import com.github.collinalpert.java2db.mappers.FieldMapper;
5+
import com.github.collinalpert.java2db.queries.Queryable;
6+
import com.github.collinalpert.java2db.queries.StoredProcedureQuery;
7+
import com.github.collinalpert.java2db.queries.async.AsyncQueryable;
8+
import com.github.collinalpert.java2db.queries.async.AsyncStoredProcedureQuery;
49
import com.mysql.cj.exceptions.CJCommunicationsException;
510
import com.mysql.cj.jdbc.exceptions.CommunicationsException;
611

@@ -10,6 +15,12 @@
1015
import java.sql.ResultSet;
1116
import java.sql.SQLException;
1217
import java.sql.Statement;
18+
import java.util.Optional;
19+
import java.util.StringJoiner;
20+
import java.util.concurrent.CompletableFuture;
21+
import java.util.function.Consumer;
22+
23+
import static com.github.collinalpert.java2db.utilities.Utilities.supplierHandling;
1324

1425
/**
1526
* @author Collin Alpert
@@ -130,7 +141,7 @@ public long update(String query) throws SQLException {
130141
var statement = this.connection.createStatement();
131142
log(query);
132143
statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
133-
return updateHelper(statement);
144+
return updateInternal(statement);
134145
}
135146

136147
/**
@@ -149,17 +160,7 @@ public long update(String query, Object... params) throws SQLException {
149160

150161
log(query);
151162
statement.executeUpdate();
152-
return updateHelper(statement);
153-
}
154-
155-
private long updateHelper(Statement statement) throws SQLException {
156-
statement.closeOnCompletion();
157-
var set = statement.getGeneratedKeys();
158-
if (set.next()) {
159-
return set.getLong(1);
160-
}
161-
162-
return -1;
163+
return updateInternal(statement);
163164
}
164165

165166
/**
@@ -194,14 +195,47 @@ public void close() {
194195
}
195196
}
196197

198+
public <T> Optional<T> callFunction(Class<T> returnType, String functionName, Object... arguments) throws SQLException {
199+
var joiner = new StringJoiner(",");
200+
for (int i = 0; i < arguments.length; i++) {
201+
joiner.add("?");
202+
}
203+
204+
try (var set = execute(String.format("select %s(%s);", functionName, joiner.toString()), arguments)) {
205+
return new FieldMapper<>(returnType).map(set);
206+
}
207+
}
208+
209+
public <T> CompletableFuture<Optional<T>> callFunctionAsync(Consumer<SQLException> exceptionHandler, Class<T> returnType, String functionName, Object... arguments) {
210+
return CompletableFuture.supplyAsync(supplierHandling(() -> this.callFunction(returnType, functionName, arguments), exceptionHandler));
211+
}
212+
213+
public <T> Queryable<T> callStoredProcedure(Class<T> returnType, String storedProcedureName, Object... arguments) {
214+
return new StoredProcedureQuery<>(returnType, this, storedProcedureName, arguments);
215+
}
216+
217+
public <T> AsyncQueryable<T> callStoredProcedureAsync(Class<T> returnType, String storedProcedureName, Object... arguments) {
218+
return new AsyncStoredProcedureQuery<>(returnType, this, storedProcedureName, arguments);
219+
}
220+
197221
/**
198222
* Prints queries to the console, while considering the {@link DBConnection#LOG_QUERIES} constant.
199223
*
200224
* @param text The message to print.
201225
*/
202226
private void log(String text) {
203-
if (DBConnection.LOG_QUERIES) {
227+
if (LOG_QUERIES) {
204228
System.out.println(text);
205229
}
206230
}
231+
232+
private long updateInternal(Statement statement) throws SQLException {
233+
statement.closeOnCompletion();
234+
var set = statement.getGeneratedKeys();
235+
if (set.next()) {
236+
return set.getLong(1);
237+
}
238+
239+
return -1;
240+
}
207241
}

src/main/java/com/github/collinalpert/java2db/database/ForeignKeyReference.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.lang.reflect.Field;
66

77
/**
8-
* Describes a foreign key reference to a specific table. This represents a field marked with the {@link com.github.collinalpert.java2db.annotations.ForeignKeyEntity} attribute.
8+
* Describes a foreign key reference to a specific table. This represents a field marked with the {@link ForeignKeyEntity} attribute.
99
*
1010
* @author Collin Alpert
1111
*/

src/main/java/com/github/collinalpert/java2db/mappers/BaseMapper.java renamed to src/main/java/com/github/collinalpert/java2db/mappers/EntityMapper.java

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
*
3737
* @author Collin Alpert
3838
*/
39-
public class BaseMapper<E extends BaseEntity> implements Mappable<E> {
39+
public class EntityMapper<E extends BaseEntity> implements Mappable<E> {
4040

4141
private static final TableModule tableModule;
4242

@@ -45,9 +45,11 @@ public class BaseMapper<E extends BaseEntity> implements Mappable<E> {
4545
}
4646

4747
private Class<E> clazz;
48+
private final Map<String, String> aliases;
4849

49-
public BaseMapper(Class<E> clazz) {
50+
public EntityMapper(Class<E> clazz) {
5051
this.clazz = clazz;
52+
this.aliases = FieldModule.getInstance().getAliases(clazz);
5153
}
5254

5355
/**
@@ -58,13 +60,13 @@ public BaseMapper(Class<E> clazz) {
5860
* @throws SQLException if the {@link ResultSet#next()} call does not work as expected or if the entity fields cannot be set.
5961
*/
6062
@Override
61-
public Optional<E> map(ResultSet set, Map<String, String> aliases) throws SQLException {
63+
public Optional<E> map(ResultSet set) throws SQLException {
6264
E entity = IoC.createInstance(this.clazz);
6365
if (!set.next()) {
6466
return Optional.empty();
6567
}
6668

67-
setFields(set, entity, aliases);
69+
setFields(set, entity);
6870
set.close();
6971
return Optional.of(entity);
7072
}
@@ -77,9 +79,9 @@ public Optional<E> map(ResultSet set, Map<String, String> aliases) throws SQLExc
7779
* @throws SQLException if the {@link ResultSet#next()} call does not work as expected or if the entity fields cannot be set.
7880
*/
7981
@Override
80-
public List<E> mapToList(ResultSet set, Map<String, String> aliases) throws SQLException {
82+
public List<E> mapToList(ResultSet set) throws SQLException {
8183
var list = new ArrayList<E>();
82-
mapInternal(set, list::add, aliases);
84+
mapInternal(set, list::add);
8385
return list;
8486
}
8587

@@ -91,9 +93,9 @@ public List<E> mapToList(ResultSet set, Map<String, String> aliases) throws SQLE
9193
* @throws SQLException if the {@link ResultSet#next()} call does not work as expected or if the entity fields cannot be set.
9294
*/
9395
@Override
94-
public Stream<E> mapToStream(ResultSet set, Map<String, String> aliases) throws SQLException {
96+
public Stream<E> mapToStream(ResultSet set) throws SQLException {
9597
var builder = Stream.<E>builder();
96-
mapInternal(set, builder::add, aliases);
98+
mapInternal(set, builder::add);
9799
return builder.build();
98100
}
99101

@@ -105,9 +107,9 @@ public Stream<E> mapToStream(ResultSet set, Map<String, String> aliases) throws
105107
* @throws SQLException if the {@link ResultSet#next()} call does not work as expected or if the entity fields cannot be set.
106108
*/
107109
@Override
108-
public E[] mapToArray(ResultSet set, Map<String, String> aliases) throws SQLException {
110+
public E[] mapToArray(ResultSet set) throws SQLException {
109111
var module = new ArrayModule<>(this.clazz, 20);
110-
mapInternal(set, module::addElement, aliases);
112+
mapInternal(set, module::addElement);
111113
return module.getArray();
112114
}
113115

@@ -117,16 +119,15 @@ public E[] mapToArray(ResultSet set, Map<String, String> aliases) throws SQLExce
117119
* @param set The {@code ResultSet} to get the data from.
118120
* @param keyMapping The key function of the map.
119121
* @param valueMapping The value function of the map.
120-
* @param aliases A map of column aliases needed to retrieve column data from the {@code ResultSet}.
121122
* @param <K> The type of the keys in the map.
122123
* @param <V> The type of the values in the map.
123124
* @return A {@code Map} containing the {@code ResultSet}s data.
124125
* @throws SQLException In case the {@code ResultSet} can't be read.
125126
*/
126127
@Override
127-
public <K, V> Map<K, V> mapToMap(ResultSet set, Function<E, K> keyMapping, Function<E, V> valueMapping, Map<String, String> aliases) throws SQLException {
128+
public <K, V> Map<K, V> mapToMap(ResultSet set, Function<E, K> keyMapping, Function<E, V> valueMapping) throws SQLException {
128129
var map = new HashMap<K, V>();
129-
mapInternal(set, x -> map.put(keyMapping.apply(x), valueMapping.apply(x)), aliases);
130+
mapInternal(set, x -> map.put(keyMapping.apply(x), valueMapping.apply(x)));
130131
return map;
131132
}
132133

@@ -137,10 +138,10 @@ public <K, V> Map<K, V> mapToMap(ResultSet set, Function<E, K> keyMapping, Funct
137138
* @param handling The action to apply at each iteration of the given {@code ResultSet}.
138139
* @throws SQLException Handling a {@code ResultSet} can possibly result in this exception being thrown.
139140
*/
140-
private void mapInternal(ResultSet set, Consumer<E> handling, Map<String, String> aliases) throws SQLException {
141+
private void mapInternal(ResultSet set, Consumer<E> handling) throws SQLException {
141142
while (set.next()) {
142143
var entity = IoC.createInstance(this.clazz);
143-
setFields(set, entity, aliases);
144+
setFields(set, entity);
144145
handling.accept(entity);
145146
}
146147

@@ -153,8 +154,8 @@ private void mapInternal(ResultSet set, Consumer<E> handling, Map<String, String
153154
* @param set The {@link ResultSet} to get the data from.
154155
* @param entity The Java entity to fill.
155156
*/
156-
private <TEntity extends BaseEntity> void setFields(ResultSet set, TEntity entity, Map<String, String> aliases) throws SQLException {
157-
setFields(set, entity, tableModule.getTableName(entity.getClass()), aliases);
157+
private <TEntity extends BaseEntity> void setFields(ResultSet set, TEntity entity) throws SQLException {
158+
setFields(set, entity, tableModule.getTableName(entity.getClass()));
158159
}
159160

160161
/**
@@ -164,7 +165,7 @@ private <TEntity extends BaseEntity> void setFields(ResultSet set, TEntity entit
164165
* @param identifier The alias set for a certain entity used as a nested property.
165166
* @param entity The Java entity to fill.
166167
*/
167-
private <TEntity extends BaseEntity> void setFields(ResultSet set, TEntity entity, String identifier, Map<String, String> aliases) throws SQLException {
168+
private <TEntity extends BaseEntity> void setFields(ResultSet set, TEntity entity, String identifier) throws SQLException {
168169
var fieldModule = FieldModule.getInstance();
169170
var fields = fieldModule.getEntityFields(entity.getClass(), true);
170171
for (var field : fields) {
@@ -204,7 +205,7 @@ private <TEntity extends BaseEntity> void setFields(ResultSet set, TEntity entit
204205

205206
@SuppressWarnings("unchecked")
206207
var foreignKeyObject = IoC.createInstance((Class<? extends BaseEntity>) field.getType());
207-
setFields(set, foreignKeyObject, aliases.get(field.getDeclaringClass().getSimpleName().toLowerCase() + "_" + field.getName()), aliases);
208+
setFields(set, foreignKeyObject, this.aliases.get(field.getDeclaringClass().getSimpleName().toLowerCase() + "_" + field.getName()));
208209
tryAction(() -> field.set(entity, foreignKeyObject));
209210

210211
continue;

0 commit comments

Comments
 (0)