Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- options for statement configuration in BasicDAOHelper <https://github.com/fugerit-org/fj-lib/issues/114>

## [8.7.2] - 2025-11-20

### Changed

- BasicDAOHelper has method to set query timeout

## [8.7.1] - 2025-10-31
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
package org.fugerit.java.core.db.dao;

import lombok.extern.slf4j.Slf4j;
import org.fugerit.java.core.function.UnsafeSupplier;
import org.fugerit.java.core.function.UnsafeVoid;
import org.fugerit.java.core.lang.ex.ExConverUtils;
Expand All @@ -29,6 +30,7 @@
* @author Fugerit
*
*/
@Slf4j
public class DAORuntimeException extends RuntimeException {

/*
Expand Down Expand Up @@ -88,5 +90,14 @@ public static <E extends Exception> void apply( UnsafeVoid<E> fun ) {
throw convertEx( e );
}
}

public static <E extends Exception> void applySilent( UnsafeVoid<E> fun ) {
try {
fun.apply();
} catch (Exception e) {
String message = String.format( "Exception on DAORuntimeException.applySilent() %s", e.getMessage() );
log.warn( message, e );
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,25 @@
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;

import org.fugerit.java.core.db.dao.DAOException;
import org.fugerit.java.core.db.dao.DAOHelper;
import org.fugerit.java.core.db.dao.DAOUtilsNG;
import org.fugerit.java.core.db.dao.FieldFactory;
import org.fugerit.java.core.db.dao.FieldList;
import org.fugerit.java.core.db.dao.RSExtractor;
import org.fugerit.java.core.db.dao.*;
import org.fugerit.java.core.lang.helpers.StringUtils;
import org.fugerit.java.core.log.LogObject;
import org.fugerit.java.core.util.ObjectUtils;
import org.fugerit.java.core.util.checkpoint.CheckpointUtils;
import org.slf4j.Logger;

import lombok.extern.slf4j.Slf4j;

/**
* <p>BasicDAOHelper for database operation.</p>
*
* @author fugerit
*
* @author Matteo Franci a.k.a. Fugerit
*
* @param <T> the type returned by this DAOHelper
*
*
* NOTE: this object is not thread-safe
*/
@Slf4j
public class BasicDAOHelper<T> implements LogObject {
Expand All @@ -46,23 +44,28 @@ public static String fieldListToString( FieldList fl ) {
for ( int k=1; k<fl.size(); k++ ) {
buffer.append( "," );
buffer.append( fl.getField( k ).toString() );
}
}
}
}
buffer.append( "]" );
return buffer.toString();
}

private DAOContext daoContext;

private Integer queryTimeout;
// by default, do nothing
private BiFunction<PreparedStatement, DAOContext, PreparedStatement> statementHelper;

public BasicDAOHelper( DAOContext daoContext ) {
this( daoContext, null );
this( daoContext, (BiFunction<PreparedStatement, DAOContext, PreparedStatement>)null );
}

public BasicDAOHelper(DAOContext daoContext, Integer queryTimeout) {
this( daoContext, StatementHelperLibrary.hewHelperSafeSilent( StatementHelperLibrary.newHelperWithQueryTimeout( queryTimeout ) ) );
}

public BasicDAOHelper(DAOContext daoContext, BiFunction<PreparedStatement, DAOContext, PreparedStatement> statementHelper) {
this.daoContext = daoContext;
this.queryTimeout = queryTimeout;
this.statementHelper = ObjectUtils.objectWithDefault( statementHelper, StatementHelperLibrary.DEFAULT_STATEMENT_HELPER );
}

public FieldList newFieldList() {
Expand All @@ -78,16 +81,13 @@ public T loadOneHelper( SelectHelper query, RSExtractor<T> re ) throws DAOExcep
}
return res;
}

public void loadAllHelper( List<T> l, SelectHelper query, RSExtractor<T> re ) throws DAOException {
this.loadAllHelper( l, query.getQueryContent(), query.getFields(), re );
}

private PreparedStatement prepareStatement( PreparedStatement ps ) throws SQLException {
if ( this.queryTimeout != null ) {
ps.setQueryTimeout( this.queryTimeout );
}
return ps;
private PreparedStatement prepareStatement( PreparedStatement ps, DAOContext context ) {
return this.statementHelper.apply( ps, context );
}

public void loadAllHelper( List<T> l, String query, FieldList fields, RSExtractor<T> re ) throws DAOException {
Expand All @@ -99,7 +99,7 @@ public void loadAllHelper( List<T> l, String query, FieldList fields, RSExtracto
log.debug( "queryId:'{}', loadAll RSExtractor : '{}'", queryId, re);
Connection conn = this.daoContext.getConnection();
int i=0;
try ( PreparedStatement ps = this.prepareStatement( conn.prepareStatement( query ) ) ) {
try ( PreparedStatement ps = this.prepareStatement( conn.prepareStatement( query ), this.daoContext ) ) {
DAOHelper.setAll( queryId, ps, fields , log );
long executeStart = System.currentTimeMillis();
try ( ResultSet rs = ps.executeQuery() ) {
Expand All @@ -117,11 +117,11 @@ public void loadAllHelper( List<T> l, String query, FieldList fields, RSExtracto
}
log.debug("queryId:{}, loadAll END list : '{}'", queryId, l.size());
}

private int updateWorker( String queryId, FieldList fields, String query , long startTime) throws DAOException {
int res = 0;
Connection conn = this.daoContext.getConnection();
try ( PreparedStatement ps = this.prepareStatement( conn.prepareStatement( query ) ) ) {
try ( PreparedStatement ps = this.prepareStatement( conn.prepareStatement( query ), this.daoContext ) ) {
DAOHelper.setAll( queryId, ps, fields , log );
long executeStart = System.currentTimeMillis();
res = ps.executeUpdate();
Expand All @@ -132,7 +132,7 @@ private int updateWorker( String queryId, FieldList fields, String query , long
}
return res;
}

public int update( QueryHelper queryHelper ) throws DAOException {
int res = 0;
try {
Expand All @@ -149,17 +149,17 @@ public int update( QueryHelper queryHelper ) throws DAOException {
}
return res;
}

private String createSequenceQuery( String sequence ) {
return " SELECT "+sequence+".NEXTVAL FROM DUAL";
}

public BigDecimal newSequenceValue( String sequence ) throws DAOException {
BigDecimal id = null;
String sql = this.createSequenceQuery(sequence);
log.info( "newSequenceValue() sql > "+sql );
try ( Statement stm = this.daoContext.getConnection().createStatement();
ResultSet rs = stm.executeQuery( sql ) ) {
ResultSet rs = stm.executeQuery( sql ) ) {
if ( rs.next() ) {
id = rs.getBigDecimal( 1 );
}
Expand All @@ -168,35 +168,34 @@ public BigDecimal newSequenceValue( String sequence ) throws DAOException {
}
return id;
}

public SelectHelper newSelectHelper( String queryView, String tableName ) {
SelectHelper helper = null;
if ( StringUtils.isNotEmpty( queryView ) ) {
helper = new SelectHelper( tableName , this.newFieldList() );
helper.appendToQuery( " SELECT * FROM ( "+queryView+" ) v " );
helper.appendToQuery( " SELECT * FROM ( "+queryView+" ) v " );
} else {
helper = newSelectHelper( tableName );
}
return helper;
}

public SelectHelper newSelectHelper( String tableName ) {
SelectHelper query = new SelectHelper( tableName , this.newFieldList() );
query.initSelectEntity();
return query;
}

public InsertHelper newInsertHelper( String tableName ) {
return new InsertHelper( tableName , this.newFieldList() );
}

public UpdateHelper newUpdateHelper( String tableName ) {
return new UpdateHelper( tableName , this.newFieldList() );
}

public DeleteHelper newDeleteHelper( String tableName ) {
return new DeleteHelper( tableName , this.newFieldList() );
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.fugerit.java.core.db.daogen;

import org.fugerit.java.core.db.dao.DAORuntimeException;
import org.fugerit.java.core.function.SafeFunction;
import org.fugerit.java.core.function.SimpleValue;
import org.fugerit.java.core.util.ObjectUtils;

import java.sql.PreparedStatement;
import java.util.function.BiFunction;

public class StatementHelperLibrary {

private StatementHelperLibrary() {}

private static final String ATT_DAO_CONTEXT_PATTERN = "DaoContext.StatementHelper.%s.ATT_NAME";

public static final String ATT_DAO_CONTEXT_QUERY_TIMEOUT = String.format( ATT_DAO_CONTEXT_PATTERN, "queryTimeout" );

public static final String ATT_DAO_CONTEXT_FETCH_SIZE = String.format( ATT_DAO_CONTEXT_PATTERN, "fetchSize" );

public static final BiFunction<PreparedStatement, DAOContext, PreparedStatement>
DO_NOTHING_STATEMENT_HELPER = ( p, c ) -> p;

public static final BiFunction<PreparedStatement, DAOContext, PreparedStatement>
QUERY_TIMEOUT_FETCH_SIZE_STATEMENT_HELPER = newHelperPipeline( newHelperWithQueryTimeout( null ), newHelperWithFetchSize( null ) );

public static final BiFunction<PreparedStatement, DAOContext, PreparedStatement>
DEFAULT_STATEMENT_HELPER = hewHelperSafeSilent( QUERY_TIMEOUT_FETCH_SIZE_STATEMENT_HELPER );

private static <T> T resolve( DAOContext daoContext, String key, T defaultValue ) {
return ObjectUtils.objectWithDefault( (T)daoContext.getAttribute( key ), defaultValue );
}

public static DAOContext withQueryTimeout( DAOContext daoContext, Integer queryTimeout ) {
if ( queryTimeout != null ) {
daoContext.setAttribute( ATT_DAO_CONTEXT_QUERY_TIMEOUT, queryTimeout );
}
return daoContext;
}

public static DAOContext withFetchSize( DAOContext daoContext, Integer fetchSize ) {
if ( fetchSize != null ) {
daoContext.setAttribute( ATT_DAO_CONTEXT_FETCH_SIZE, fetchSize );
}
return daoContext;
}

public static BiFunction<PreparedStatement, DAOContext, PreparedStatement> newHelperWithQueryTimeout( Integer queryTimeoutSeconds ) {
return (ps, daoContext) -> {
Integer resolvedQueryTimeoutSeconds = resolve( daoContext, ATT_DAO_CONTEXT_QUERY_TIMEOUT, queryTimeoutSeconds );
SafeFunction.applyIfNotNull( resolvedQueryTimeoutSeconds,
() -> ps.setQueryTimeout( resolvedQueryTimeoutSeconds.intValue() ) );
return ps;
};
}

public static BiFunction<PreparedStatement, DAOContext, PreparedStatement> newHelperWithFetchSize( Integer fetchSize ) {
return (ps, daoContext) -> {
Integer resolvedFetchSize = resolve( daoContext, ATT_DAO_CONTEXT_FETCH_SIZE, fetchSize );
SafeFunction.applyIfNotNull( resolvedFetchSize,
() -> ps.setFetchSize( resolvedFetchSize.intValue() ) );
return ps;
};
}

public static BiFunction<PreparedStatement, DAOContext, PreparedStatement> newHelperPipeline(
BiFunction<PreparedStatement, DAOContext, PreparedStatement>... helpers) {
return (preparedStatement, daoContext) -> {
PreparedStatement ps = preparedStatement;
for ( BiFunction<PreparedStatement, DAOContext, PreparedStatement> helper : helpers ) {
ps = helper.apply(ps, daoContext);
}
return ps;
};
}
public static BiFunction<PreparedStatement, DAOContext, PreparedStatement> hewHelperSafeSilent(
BiFunction<PreparedStatement, DAOContext, PreparedStatement> helper) {
return (ps, daoContext) -> {
SimpleValue<PreparedStatement> res = new SimpleValue<>( ps );
DAORuntimeException.applySilent( () -> res.setValue( helper.apply(ps, daoContext ) ) );
return res.getValue();
};
}

}
Loading