I am trying to figure the best way to lay out this design and have been running into some issues.
I have a Dao interface, where R is the return Type and U is the database record impl:
public interface Dao<U extends UpdatableRecordImpl> {
public List<U> insert(List<U> dbRecords);
public List<U> fetchAll(Select<U> selectQuery);
}
I have a default Dao that implements Dao in the following way:
public class BasicDao<U extends UpdatableRecordImpl> implements Dao<U>{
protected final DSLContext _dslContext;
public BasicDao(Configuration configuration, T table) {
_dslContext = DSL.using(configuration);
_table = table;
}
/**
* Fetch multiple records from database
*
* @param selectQuery input query
* @return list of records representing the database records
*/
public List<U> fetchAll(Select<U> selectQuery) {
return selectQuery.fetchStream().collect(Collectors.toList());
}
/**
* Persists db records
* <p>
* Performs a batch operation for more than one record
*
* @param dbRecords list of records that need to be persisted
* @return list of records with updated with id's which were generated by database
*/
public List<U> insert(List<U> dbRecords) {
if (dbRecords.isEmpty()) {
return ImmutableList.of();
}
// prepare insert statement
Result<U> inserted = //insert records
return inserted;
}
}
Now what I'm trying to do is have a mapping layer on top of that. Such that we can have a class that will look like this:
@Override
public List<M> insert(List<M> mappedRecords) {
// Map record templates to db records
List<U> dbRecords = mapList(mappedRecords, this::map);
//Map the result of inserting to DefaultDao
return mapList(_defaultDao.insert(dbRecords), this::map);
}
@Override
public List<M> fetchAll(Select<U> select) {
return StreamEx.of(_defaultDao.fetchAll(select)).map(this::map).toList();
}
/**
* Map list of POJOs' of one type to the list of POJOs' of another type
*
* @param records list of POJOs' that need to be mapped
* @param mapper function to map a single POJO of one type to other POJO type
* @param <P> Input POJO type
* @param <B> Output POJO type
* @return
*/
protected <P, B> List<B> mapList(List<P> records, Function<P, B> mapper) {
return StreamEx.of(records).map(mapper).toList();
}
/**
* Transforms a representative record to it's database representation
* @param mappedRecord mapped representation of database record
* @return database record
*/
protected U map(M mappedRecord) {
return _mapper.map(mappedRecord);
}
/**
* Maps database record to it's mapped representation
* @param dbRecord database record
* @return representation of the database record in M type
*/
M map(U dbRecord) {
return _mapper.inverse().map(dbRecord);
}
I have tried adding a Decorator layer around BasicDao, but I run into an issue with the same closures (List<U> insert(List<U> dbRecords)
and List<M> insert(List<M> dbRecords)
have same closures).
What is the suggested way to work with this setup? I have found some hacky ways by making Dao take in two classes (return and recordImpl), but this looks hacky in the basic impl (implements Dao<U, U>
) and breaks some existing functionality in classes that do generic class bounds (List<D extends BasicDao>
).
Thanks for the help.
Aucun commentaire:
Enregistrer un commentaire