Skip to content

Commit 5bb8d59

Browse files
authored
Merge pull request #115 from fugerit-org/114-add-options-for-statement-configuration-in-basicdaohelper
feat: options for statement configuration in BasicDAOHelper #114
2 parents 7ea43ab + 5619500 commit 5bb8d59

File tree

7 files changed

+260
-38
lines changed

7 files changed

+260
-38
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- options for statement configuration in BasicDAOHelper <https://github.com/fugerit-org/fj-lib/issues/114>
13+
1014
## [8.7.2] - 2025-11-20
1115

16+
### Changed
17+
1218
- BasicDAOHelper has method to set query timeout
1319

1420
## [8.7.1] - 2025-10-31

fj-core/src/main/java/org/fugerit/java/core/db/dao/DAORuntimeException.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*/
2121
package org.fugerit.java.core.db.dao;
2222

23+
import lombok.extern.slf4j.Slf4j;
2324
import org.fugerit.java.core.function.UnsafeSupplier;
2425
import org.fugerit.java.core.function.UnsafeVoid;
2526
import org.fugerit.java.core.lang.ex.ExConverUtils;
@@ -29,6 +30,7 @@
2930
* @author Fugerit
3031
*
3132
*/
33+
@Slf4j
3234
public class DAORuntimeException extends RuntimeException {
3335

3436
/*
@@ -88,5 +90,14 @@ public static <E extends Exception> void apply( UnsafeVoid<E> fun ) {
8890
throw convertEx( e );
8991
}
9092
}
93+
94+
public static <E extends Exception> void applySilent( UnsafeVoid<E> fun ) {
95+
try {
96+
fun.apply();
97+
} catch (Exception e) {
98+
String message = String.format( "Exception on DAORuntimeException.applySilent() %s", e.getMessage() );
99+
log.warn( message, e );
100+
}
101+
}
91102

92103
}

fj-core/src/main/java/org/fugerit/java/core/db/daogen/BasicDAOHelper.java

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,25 @@
88
import java.sql.Statement;
99
import java.util.ArrayList;
1010
import java.util.List;
11+
import java.util.function.BiFunction;
1112

12-
import org.fugerit.java.core.db.dao.DAOException;
13-
import org.fugerit.java.core.db.dao.DAOHelper;
14-
import org.fugerit.java.core.db.dao.DAOUtilsNG;
15-
import org.fugerit.java.core.db.dao.FieldFactory;
16-
import org.fugerit.java.core.db.dao.FieldList;
17-
import org.fugerit.java.core.db.dao.RSExtractor;
13+
import org.fugerit.java.core.db.dao.*;
1814
import org.fugerit.java.core.lang.helpers.StringUtils;
1915
import org.fugerit.java.core.log.LogObject;
16+
import org.fugerit.java.core.util.ObjectUtils;
2017
import org.fugerit.java.core.util.checkpoint.CheckpointUtils;
2118
import org.slf4j.Logger;
2219

2320
import lombok.extern.slf4j.Slf4j;
2421

2522
/**
2623
* <p>BasicDAOHelper for database operation.</p>
27-
*
28-
* @author fugerit
24+
*
25+
* @author Matteo Franci a.k.a. Fugerit
2926
*
3027
* @param <T> the type returned by this DAOHelper
31-
*
28+
*
29+
* NOTE: this object is not thread-safe
3230
*/
3331
@Slf4j
3432
public class BasicDAOHelper<T> implements LogObject {
@@ -46,23 +44,28 @@ public static String fieldListToString( FieldList fl ) {
4644
for ( int k=1; k<fl.size(); k++ ) {
4745
buffer.append( "," );
4846
buffer.append( fl.getField( k ).toString() );
49-
}
50-
}
47+
}
48+
}
5149
buffer.append( "]" );
5250
return buffer.toString();
5351
}
54-
52+
5553
private DAOContext daoContext;
5654

57-
private Integer queryTimeout;
55+
// by default, do nothing
56+
private BiFunction<PreparedStatement, DAOContext, PreparedStatement> statementHelper;
5857

5958
public BasicDAOHelper( DAOContext daoContext ) {
60-
this( daoContext, null );
59+
this( daoContext, (BiFunction<PreparedStatement, DAOContext, PreparedStatement>)null );
6160
}
6261

6362
public BasicDAOHelper(DAOContext daoContext, Integer queryTimeout) {
63+
this( daoContext, StatementHelperLibrary.hewHelperSafeSilent( StatementHelperLibrary.newHelperWithQueryTimeout( queryTimeout ) ) );
64+
}
65+
66+
public BasicDAOHelper(DAOContext daoContext, BiFunction<PreparedStatement, DAOContext, PreparedStatement> statementHelper) {
6467
this.daoContext = daoContext;
65-
this.queryTimeout = queryTimeout;
68+
this.statementHelper = ObjectUtils.objectWithDefault( statementHelper, StatementHelperLibrary.DEFAULT_STATEMENT_HELPER );
6669
}
6770

6871
public FieldList newFieldList() {
@@ -78,16 +81,13 @@ public T loadOneHelper( SelectHelper query, RSExtractor<T> re ) throws DAOExcep
7881
}
7982
return res;
8083
}
81-
84+
8285
public void loadAllHelper( List<T> l, SelectHelper query, RSExtractor<T> re ) throws DAOException {
8386
this.loadAllHelper( l, query.getQueryContent(), query.getFields(), re );
8487
}
8588

86-
private PreparedStatement prepareStatement( PreparedStatement ps ) throws SQLException {
87-
if ( this.queryTimeout != null ) {
88-
ps.setQueryTimeout( this.queryTimeout );
89-
}
90-
return ps;
89+
private PreparedStatement prepareStatement( PreparedStatement ps, DAOContext context ) {
90+
return this.statementHelper.apply( ps, context );
9191
}
9292

9393
public void loadAllHelper( List<T> l, String query, FieldList fields, RSExtractor<T> re ) throws DAOException {
@@ -99,7 +99,7 @@ public void loadAllHelper( List<T> l, String query, FieldList fields, RSExtracto
9999
log.debug( "queryId:'{}', loadAll RSExtractor : '{}'", queryId, re);
100100
Connection conn = this.daoContext.getConnection();
101101
int i=0;
102-
try ( PreparedStatement ps = this.prepareStatement( conn.prepareStatement( query ) ) ) {
102+
try ( PreparedStatement ps = this.prepareStatement( conn.prepareStatement( query ), this.daoContext ) ) {
103103
DAOHelper.setAll( queryId, ps, fields , log );
104104
long executeStart = System.currentTimeMillis();
105105
try ( ResultSet rs = ps.executeQuery() ) {
@@ -117,11 +117,11 @@ public void loadAllHelper( List<T> l, String query, FieldList fields, RSExtracto
117117
}
118118
log.debug("queryId:{}, loadAll END list : '{}'", queryId, l.size());
119119
}
120-
120+
121121
private int updateWorker( String queryId, FieldList fields, String query , long startTime) throws DAOException {
122122
int res = 0;
123123
Connection conn = this.daoContext.getConnection();
124-
try ( PreparedStatement ps = this.prepareStatement( conn.prepareStatement( query ) ) ) {
124+
try ( PreparedStatement ps = this.prepareStatement( conn.prepareStatement( query ), this.daoContext ) ) {
125125
DAOHelper.setAll( queryId, ps, fields , log );
126126
long executeStart = System.currentTimeMillis();
127127
res = ps.executeUpdate();
@@ -132,7 +132,7 @@ private int updateWorker( String queryId, FieldList fields, String query , long
132132
}
133133
return res;
134134
}
135-
135+
136136
public int update( QueryHelper queryHelper ) throws DAOException {
137137
int res = 0;
138138
try {
@@ -149,17 +149,17 @@ public int update( QueryHelper queryHelper ) throws DAOException {
149149
}
150150
return res;
151151
}
152-
152+
153153
private String createSequenceQuery( String sequence ) {
154154
return " SELECT "+sequence+".NEXTVAL FROM DUAL";
155155
}
156-
156+
157157
public BigDecimal newSequenceValue( String sequence ) throws DAOException {
158158
BigDecimal id = null;
159159
String sql = this.createSequenceQuery(sequence);
160160
log.info( "newSequenceValue() sql > "+sql );
161161
try ( Statement stm = this.daoContext.getConnection().createStatement();
162-
ResultSet rs = stm.executeQuery( sql ) ) {
162+
ResultSet rs = stm.executeQuery( sql ) ) {
163163
if ( rs.next() ) {
164164
id = rs.getBigDecimal( 1 );
165165
}
@@ -168,35 +168,34 @@ public BigDecimal newSequenceValue( String sequence ) throws DAOException {
168168
}
169169
return id;
170170
}
171-
171+
172172
public SelectHelper newSelectHelper( String queryView, String tableName ) {
173173
SelectHelper helper = null;
174174
if ( StringUtils.isNotEmpty( queryView ) ) {
175175
helper = new SelectHelper( tableName , this.newFieldList() );
176-
helper.appendToQuery( " SELECT * FROM ( "+queryView+" ) v " );
176+
helper.appendToQuery( " SELECT * FROM ( "+queryView+" ) v " );
177177
} else {
178178
helper = newSelectHelper( tableName );
179179
}
180180
return helper;
181181
}
182-
182+
183183
public SelectHelper newSelectHelper( String tableName ) {
184184
SelectHelper query = new SelectHelper( tableName , this.newFieldList() );
185185
query.initSelectEntity();
186186
return query;
187187
}
188-
188+
189189
public InsertHelper newInsertHelper( String tableName ) {
190190
return new InsertHelper( tableName , this.newFieldList() );
191191
}
192-
192+
193193
public UpdateHelper newUpdateHelper( String tableName ) {
194194
return new UpdateHelper( tableName , this.newFieldList() );
195195
}
196-
196+
197197
public DeleteHelper newDeleteHelper( String tableName ) {
198198
return new DeleteHelper( tableName , this.newFieldList() );
199199
}
200-
201-
200+
202201
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package org.fugerit.java.core.db.daogen;
2+
3+
import org.fugerit.java.core.db.dao.DAORuntimeException;
4+
import org.fugerit.java.core.function.SafeFunction;
5+
import org.fugerit.java.core.function.SimpleValue;
6+
import org.fugerit.java.core.util.ObjectUtils;
7+
8+
import java.sql.PreparedStatement;
9+
import java.util.function.BiFunction;
10+
11+
public class StatementHelperLibrary {
12+
13+
private StatementHelperLibrary() {}
14+
15+
private static final String ATT_DAO_CONTEXT_PATTERN = "DaoContext.StatementHelper.%s.ATT_NAME";
16+
17+
public static final String ATT_DAO_CONTEXT_QUERY_TIMEOUT = String.format( ATT_DAO_CONTEXT_PATTERN, "queryTimeout" );
18+
19+
public static final String ATT_DAO_CONTEXT_FETCH_SIZE = String.format( ATT_DAO_CONTEXT_PATTERN, "fetchSize" );
20+
21+
public static final BiFunction<PreparedStatement, DAOContext, PreparedStatement>
22+
DO_NOTHING_STATEMENT_HELPER = ( p, c ) -> p;
23+
24+
public static final BiFunction<PreparedStatement, DAOContext, PreparedStatement>
25+
QUERY_TIMEOUT_FETCH_SIZE_STATEMENT_HELPER = newHelperPipeline( newHelperWithQueryTimeout( null ), newHelperWithFetchSize( null ) );
26+
27+
public static final BiFunction<PreparedStatement, DAOContext, PreparedStatement>
28+
DEFAULT_STATEMENT_HELPER = hewHelperSafeSilent( QUERY_TIMEOUT_FETCH_SIZE_STATEMENT_HELPER );
29+
30+
private static <T> T resolve( DAOContext daoContext, String key, T defaultValue ) {
31+
return ObjectUtils.objectWithDefault( (T)daoContext.getAttribute( key ), defaultValue );
32+
}
33+
34+
public static DAOContext withQueryTimeout( DAOContext daoContext, Integer queryTimeout ) {
35+
if ( queryTimeout != null ) {
36+
daoContext.setAttribute( ATT_DAO_CONTEXT_QUERY_TIMEOUT, queryTimeout );
37+
}
38+
return daoContext;
39+
}
40+
41+
public static DAOContext withFetchSize( DAOContext daoContext, Integer fetchSize ) {
42+
if ( fetchSize != null ) {
43+
daoContext.setAttribute( ATT_DAO_CONTEXT_FETCH_SIZE, fetchSize );
44+
}
45+
return daoContext;
46+
}
47+
48+
public static BiFunction<PreparedStatement, DAOContext, PreparedStatement> newHelperWithQueryTimeout( Integer queryTimeoutSeconds ) {
49+
return (ps, daoContext) -> {
50+
Integer resolvedQueryTimeoutSeconds = resolve( daoContext, ATT_DAO_CONTEXT_QUERY_TIMEOUT, queryTimeoutSeconds );
51+
SafeFunction.applyIfNotNull( resolvedQueryTimeoutSeconds,
52+
() -> ps.setQueryTimeout( resolvedQueryTimeoutSeconds.intValue() ) );
53+
return ps;
54+
};
55+
}
56+
57+
public static BiFunction<PreparedStatement, DAOContext, PreparedStatement> newHelperWithFetchSize( Integer fetchSize ) {
58+
return (ps, daoContext) -> {
59+
Integer resolvedFetchSize = resolve( daoContext, ATT_DAO_CONTEXT_FETCH_SIZE, fetchSize );
60+
SafeFunction.applyIfNotNull( resolvedFetchSize,
61+
() -> ps.setFetchSize( resolvedFetchSize.intValue() ) );
62+
return ps;
63+
};
64+
}
65+
66+
public static BiFunction<PreparedStatement, DAOContext, PreparedStatement> newHelperPipeline(
67+
BiFunction<PreparedStatement, DAOContext, PreparedStatement>... helpers) {
68+
return (preparedStatement, daoContext) -> {
69+
PreparedStatement ps = preparedStatement;
70+
for ( BiFunction<PreparedStatement, DAOContext, PreparedStatement> helper : helpers ) {
71+
ps = helper.apply(ps, daoContext);
72+
}
73+
return ps;
74+
};
75+
}
76+
public static BiFunction<PreparedStatement, DAOContext, PreparedStatement> hewHelperSafeSilent(
77+
BiFunction<PreparedStatement, DAOContext, PreparedStatement> helper) {
78+
return (ps, daoContext) -> {
79+
SimpleValue<PreparedStatement> res = new SimpleValue<>( ps );
80+
DAORuntimeException.applySilent( () -> res.setValue( helper.apply(ps, daoContext ) ) );
81+
return res.getValue();
82+
};
83+
}
84+
85+
}

0 commit comments

Comments
 (0)