[Major] Extended StrolchDao with paging feature

This commit is contained in:
Robert von Burg 2019-03-05 17:57:59 +01:00
parent a3264fb99c
commit 45189a5bc3
6 changed files with 209 additions and 130 deletions

View File

@ -39,19 +39,29 @@ import li.strolch.model.StrolchRootElement;
*/
public interface StrolchDao<T extends StrolchRootElement> {
/**
* Returns true if this {@link StrolchDao} supports paging, i.e. the methods with a limit and offset may be used
*
* @return true if this {@link StrolchDao} supports paging, i.e. the methods with a limit and offset may be used
*/
boolean supportsPaging();
/**
* Returns the number of elements in the underlying persistence layer, regardless of type
*
* @return the number of elements in the underlying persistence layer
*/
public long querySize();
long querySize();
/**
* Returns the number of elements in the underlying persistence layer for the given type
* Returns the number of elements in the underlying persistence layer for the given type(s)
*
* @return the number of elements in the underlying persistence layer for the given type
* @param types
* the type(s) to query the size for
*
* @return the number of elements in the underlying persistence layer for the given type(s)
*/
public long querySize(String type);
long querySize(String... types);
/**
* Queries the current list of types from the underlying persistence layer
@ -61,20 +71,62 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if something goes wrong
*/
public Set<String> queryTypes() throws StrolchPersistenceException;
Set<String> queryTypes() throws StrolchPersistenceException;
/**
* Queries and returns all elements regardless of type
*
* @return all elements regardless of type
*
* @throws StrolchPersistenceException
* if something goes wrong
*/
List<T> queryAll() throws StrolchPersistenceException;
/**
* Queries and returns all elements regardless of type
*
* @param limit
* the max amount, or @{@link Integer#MAX_VALUE} for all
* @param offset
* if max amount defined, then the offset to start from
*
* @return all elements regardless of type
*
* @throws StrolchPersistenceException
* if something goes wrong
*/
List<T> queryAll(long limit, long offset) throws StrolchPersistenceException;
/**
* Queries and returns all elements of the given type
*
* @param type
* the type of element to return
* @param types
* the type(s) of element(s) to return
*
* @return all elements of the given type
*
* @throws StrolchPersistenceException
* if something goes wrong
*/
public List<T> queryAll(String type) throws StrolchPersistenceException;
List<T> queryAll(String... types) throws StrolchPersistenceException;
/**
* Queries and returns all elements of the given type
*
* @param limit
* the max amount, or @{@link Integer#MAX_VALUE} for all
* @param offset
* if max amount defined, then the offset to start from
* @param types
* the type(s) of element(s) to return
*
* @return all elements of the given type
*
* @throws StrolchPersistenceException
* if something goes wrong
*/
List<T> queryAll(long limit, long offset, String... types) throws StrolchPersistenceException;
/**
* Persists the given element. The element must not yet exist
@ -85,7 +137,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if the element already exists
*/
public void save(T element) throws StrolchPersistenceException;
void save(T element) throws StrolchPersistenceException;
/**
* Persists the given list of elements. None of the elements may already exists
@ -96,7 +148,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if any of the elements already exist
*/
public void saveAll(List<T> elements) throws StrolchPersistenceException;
void saveAll(List<T> elements) throws StrolchPersistenceException;
/**
* Updates the given element. The element must already exist
@ -107,7 +159,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if the element does not exist
*/
public void update(T element) throws StrolchPersistenceException;
void update(T element) throws StrolchPersistenceException;
/**
* Updates the given list of elements. Each element must already exist
@ -118,7 +170,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if any of the elements do not exist
*/
public void updateAll(List<T> elements) throws StrolchPersistenceException;
void updateAll(List<T> elements) throws StrolchPersistenceException;
/**
* <p>
@ -136,7 +188,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if the element does not exist
*/
public void remove(T element) throws StrolchPersistenceException;
void remove(T element) throws StrolchPersistenceException;
/**
* <p>
@ -154,7 +206,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if any of the elements do not exist
*/
public void removeAll(List<T> elements) throws StrolchPersistenceException;
void removeAll(List<T> elements) throws StrolchPersistenceException;
/**
* <p>
@ -171,7 +223,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if something goes wrong
*/
public long removeAll() throws StrolchPersistenceException;
long removeAll() throws StrolchPersistenceException;
/**
* <p>
@ -191,7 +243,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if something goes wrong
*/
public long removeAllBy(String type) throws StrolchPersistenceException;
long removeAllBy(String type) throws StrolchPersistenceException;
/**
* <p>
@ -214,7 +266,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if something goes wrong
*/
public T queryBy(String type, String id, int version) throws StrolchPersistenceException;
T queryBy(String type, String id, int version) throws StrolchPersistenceException;
/**
* Queries and returns all the versions of the element with the given type and ID
@ -229,7 +281,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if something goes wrong
*/
public List<T> queryVersionsFor(String type, String id) throws StrolchPersistenceException;
List<T> queryVersionsFor(String type, String id) throws StrolchPersistenceException;
/**
* Queries and returns the latest version of the element with the given type and ID, -1 if no version available
@ -244,7 +296,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if something goes wrong
*/
public int queryLatestVersionFor(String type, String id) throws StrolchPersistenceException;
int queryLatestVersionFor(String type, String id) throws StrolchPersistenceException;
/**
* Queries and returns the number of versions for the element with the given type and ID
@ -259,17 +311,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if something goes wrong
*/
public long queryVersionsSizeFor(String type, String id) throws StrolchPersistenceException;
/**
* Queries and returns all elements regardless of type
*
* @return all elements regardless of type
*
* @throws StrolchPersistenceException
* if something goes wrong
*/
public List<T> queryAll() throws StrolchPersistenceException;
long queryVersionsSizeFor(String type, String id) throws StrolchPersistenceException;
/**
* <p>
@ -288,7 +330,7 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if the element/version does not exist
*/
public void removeVersion(T element) throws StrolchPersistenceException;
void removeVersion(T element) throws StrolchPersistenceException;
/**
* Causes the DAO to flush any actions which have not yet been sent to the underlying persistence layer
@ -296,5 +338,5 @@ public interface StrolchDao<T extends StrolchRootElement> {
* @throws StrolchPersistenceException
* if something goes wrong
*/
public void flush() throws StrolchPersistenceException;
void flush() throws StrolchPersistenceException;
}

View File

@ -94,14 +94,7 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
@Override
protected void internalSave(final Activity activity) {
String sql;
if (this.dataType == DataType.xml)
sql = insertAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = insertAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getSql(insertAsXmlSqlS, insertAsJsonSqlS);
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {
@ -193,14 +186,7 @@ public class PostgreSqlActivityDao extends PostgresqlDao<Activity> implements Ac
activity.getVersion()));
}
String sql;
if (this.dataType == DataType.xml)
sql = updateAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = updateAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getSql(updateAsXmlSqlS, updateAsJsonSqlS);
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {

View File

@ -94,14 +94,7 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
@Override
protected void internalSave(final Order order) {
String sql;
if (this.dataType == DataType.xml)
sql = insertAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = insertAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getSql(insertAsXmlSqlS, insertAsJsonSqlS);
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {
@ -193,14 +186,7 @@ public class PostgreSqlOrderDao extends PostgresqlDao<Order> implements OrderDao
order.getVersion()));
}
String sql;
if (this.dataType == DataType.xml)
sql = updateAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = updateAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getSql(updateAsXmlSqlS, updateAsJsonSqlS);
// now we update the existing object
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {

View File

@ -94,14 +94,7 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
@Override
protected void internalSave(final Resource resource) {
String sql;
if (this.dataType == DataType.xml)
sql = insertAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = insertAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getSql(insertAsXmlSqlS, insertAsJsonSqlS);
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {
@ -193,14 +186,7 @@ public class PostgreSqlResourceDao extends PostgresqlDao<Resource> implements Re
}
// now we update the existing object
String sql;
if (this.dataType == DataType.xml)
sql = updateAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = updateAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getSql(updateAsXmlSqlS, updateAsJsonSqlS);
try (PreparedStatement preparedStatement = this.connection.prepareStatement(sql)) {

View File

@ -33,29 +33,37 @@ import org.postgresql.util.PGobject;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
@SuppressWarnings("nls")
public abstract class PostgresqlDao<T extends StrolchRootElement> implements StrolchDao<T> {
private static final String querySizeSqlS = "select count(*) from {0} where latest = true";
private static final String querySizeOfTypeSqlS = "select count(*) from {0} where type = ? and latest = true";
private static final String querySizeOfTypeSqlS = "select count(*) from {0} where type = ANY(?) and latest = true";
private static final String querySizeOfElementSqlS = "select count(*) from {0} where type = ? and id = ?";
private static final String queryTypesSqlS = "select distinct type from {0} where latest = true";
private static final String queryLatestVersionNumberForSqlS = "select count(*), max(version) from {0} where type = ? and id = ?";
private static final String queryVersionsSizeForSqlS = "select count(*) from {0} where type = ? and id = ?";
private static final String updateLatestSqlS = "update {0} set latest = true where type = ? and id = ? and version = ?";
private static final String deleteElementSqlS = "delete from {0} where id = ?";
private static final String deleteVersionSqlS = "delete from {0} where type = ? and id = ? and version = ? and latest = true";
private static final String updateLatestSqlS = "update {0} set latest = true where type = ? and id = ? and version = ?";
private static final String deleteAllSqlS = "delete from {0}";
private static final String deleteAllByTypeSqlS = "delete from {0} where type = ?";
private static final String queryByVersionAsXmlSqlS = "select version, asxml from {0} where type = ? and id = ? and version = ?";
private static final String queryByVersionAsJsonSqlS = "select version, asjson from {0} where type = ? and id = ? and version = ?";
private static final String queryVersionsAsXmlForSqlS = "select asxml from {0} where type = ? and id = ? order by version";
private static final String queryVersionsAsJsonForSqlS = "select asjson from {0} where type = ? and id = ? order by version";
private static final String queryAllAsXmlSqlS = "select id, type, asxml from {0} where latest = true";
private static final String queryAllAsXmlLimitSqlS = "select id, type, asxml from {0} where latest = true order by id limit {1} offset {2}";
private static final String queryAllAsJsonSqlS = "select id, type, asjson from {0} where latest = true";
private static final String queryAllByTypeAsXmlSqlS = "select id, asxml from {0} where type = ? and latest = true";
private static final String queryAllByTypeAsJsonSqlS = "select id, asjson from {0} where type = ? and latest = true";
private static final String queryAllAsJsonLimitSqlS = "select id, type, asjson from {0} where latest = true order by id limit {1} offset {2}";
private static final String queryAllByTypeAsXmlSqlS = "select id, type, asxml from {0} where type = ANY(?) and latest = true";
private static final String queryAllByTypeAsXmlLimitSqlS = "select id, type, asxml from {0} where type = ANY(?) and latest = true order by id limit {1} offset {2}";
private static final String queryAllByTypeAsJsonSqlS = "select id, type, asjson from {0} where type = ANY(?) and latest = true";
private static final String queryAllByTypeAsJsonLimitSqlS = "select id, type, asjson from {0} where type = ANY(?) and latest = true order by id limit {1} offset {2}";
protected final DataType dataType;
protected Connection connection;
@ -72,6 +80,11 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
this.commands = new ArrayList<>();
}
@Override
public boolean supportsPaging() {
return true;
}
public DataType getDataType() {
return this.dataType;
}
@ -144,10 +157,16 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
@Override
public long querySize(String type) {
public long querySize(String... types) {
if (types.length == 0)
return querySize();
String sql = MessageFormat.format(querySizeOfTypeSqlS, getTableName());
try (PreparedStatement statement = this.connection.prepareStatement(sql)) {
statement.setString(1, type);
Array typesArray = statement.getConnection().createArrayOf("varchar", types);
statement.setArray(1, typesArray);
try (ResultSet result = statement.executeQuery()) {
result.next();
@ -161,9 +180,10 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public Set<String> queryTypes() {
Set<String> keySet = new HashSet<>();
String sql = MessageFormat.format(queryTypesSqlS, getTableName());
Set<String> keySet = new HashSet<>();
try (PreparedStatement statement = this.connection.prepareStatement(sql)) {
try (ResultSet result = statement.executeQuery()) {
@ -182,14 +202,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public T queryBy(String type, String id, int versionNr) {
String sql;
if (this.dataType == DataType.xml)
sql = queryByVersionAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = queryByVersionAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getSql(queryByVersionAsXmlSqlS, queryByVersionAsJsonSqlS);
try (PreparedStatement statement = this.connection.prepareStatement(sql)) {
statement.setString(1, type);
@ -220,17 +233,9 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public List<T> queryVersionsFor(String type, String id) {
String sql = getSql(queryVersionsAsXmlForSqlS, queryVersionsAsJsonForSqlS);
List<T> list = new ArrayList<>(1);
String sql;
if (this.dataType == DataType.xml)
sql = queryVersionsAsXmlForSqlS;
else if (this.dataType == DataType.json)
sql = queryVersionsAsJsonForSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
try (PreparedStatement statement = this.connection.prepareStatement(sql)) {
statement.setString(1, type);
statement.setString(2, id);
@ -296,17 +301,16 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public List<T> queryAll() {
return queryAll(Integer.MAX_VALUE, 0);
}
@Override
public List<T> queryAll(long limit, long offset) {
List<T> list = new ArrayList<>();
String sql;
if (this.dataType == DataType.xml)
sql = queryAllAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = queryAllAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getLimitSql(limit, offset, queryAllAsXmlSqlS, queryAllAsJsonSqlS, queryAllAsXmlLimitSqlS,
queryAllAsJsonLimitSqlS);
try (PreparedStatement statement = this.connection.prepareStatement(sql)) {
@ -326,25 +330,29 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
@Override
public List<T> queryAll(String type) {
public List<T> queryAll(String... types) {
return queryAll(Integer.MAX_VALUE, 0, types);
}
@Override
public List<T> queryAll(long limit, long offset, String... types) {
if (types.length == 0)
return queryAll(limit, offset);
List<T> list = new ArrayList<>();
String sql;
if (this.dataType == DataType.xml)
sql = queryAllByTypeAsXmlSqlS;
else if (this.dataType == DataType.json)
sql = queryAllByTypeAsJsonSqlS;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
sql = MessageFormat.format(sql, getTableName());
String sql = getLimitSql(limit, offset, queryAllByTypeAsXmlSqlS, queryAllByTypeAsJsonSqlS,
queryAllByTypeAsXmlLimitSqlS, queryAllByTypeAsJsonLimitSqlS);
try (PreparedStatement statement = this.connection.prepareStatement(sql)) {
statement.setString(1, type);
Array typesArray = statement.getConnection().createArrayOf("varchar", types);
statement.setArray(1, typesArray);
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
String id = result.getString("id");
String type = result.getString("type");
list.add(parseDbObject(result, id, type));
}
@ -356,6 +364,37 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
}
protected String getLimitSql(long limit, long offset, String xmlSql, String jsonSql, String xmlLimitSql,
String jsonLimitSql) {
String sql;
if (limit == Integer.MAX_VALUE) {
return getSql(xmlSql, jsonSql);
}
if (this.dataType == DataType.xml)
sql = xmlLimitSql;
else if (this.dataType == DataType.json)
sql = jsonLimitSql;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
return MessageFormat.format(sql, getTableName(), limit, offset);
}
protected String getSql(String xmlSql, String jsonSql) {
String sql;
if (this.dataType == DataType.xml)
sql = xmlSql;
else if (this.dataType == DataType.json)
sql = jsonSql;
else
throw new IllegalStateException("Unhandled DataType " + this.dataType);
return MessageFormat.format(sql, getTableName());
}
@Override
public void save(T res) {
this.commands.add(txResult -> {

View File

@ -37,6 +37,11 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
this.tx = strolchTx.getTx();
}
@Override
public boolean supportsPaging() {
return false;
}
protected abstract String getClassType();
protected IdOfSubTypeRef getIdRef(String type, String id) {
@ -52,7 +57,6 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
long size = 0;
Set<String> types = queryTypes();
for (String type : types) {
SubTypeRef subTypeRef = getTypeRef(type);
size += this.tx.getMetadataDao().querySize(subTypeRef);
}
@ -60,9 +64,23 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
}
@Override
public long querySize(String type) {
SubTypeRef subTypeRef = getTypeRef(type);
return this.tx.getMetadataDao().querySize(subTypeRef);
public long querySize(String... types) {
if (types.length == 0)
return querySize();
if (types.length == 1) {
SubTypeRef subTypeRef = getTypeRef(types[0]);
return this.tx.getMetadataDao().querySize(subTypeRef);
}
int size = 0;
for (String type : types) {
SubTypeRef subTypeRef = getTypeRef(type);
size += this.tx.getMetadataDao().querySize(subTypeRef);
}
return size;
}
@Override
@ -84,8 +102,20 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
}
@Override
public List<T> queryAll(String type) {
return this.tx.getObjectDao().queryAll(getTypeRef(type));
public List<T> queryAll(String... types) {
if (types.length == 0)
return queryAll();
if (types.length == 1) {
return this.tx.getObjectDao().queryAll(getTypeRef(types[0]));
}
List<T> objects = new ArrayList<>();
for (String type : types) {
objects.addAll(this.tx.getObjectDao().queryAll(getTypeRef(type)));
}
return objects;
}
@Override
@ -135,6 +165,16 @@ public abstract class AbstractDao<T extends StrolchRootElement> implements Strol
// nothing to do
}
@Override
public List<T> queryAll(long limit, long offset) throws StrolchPersistenceException {
throw new UnsupportedOperationException("Paging not supported! Check first with supportsPaging()");
}
@Override
public List<T> queryAll(long limit, long offset, String... types) throws StrolchPersistenceException {
throw new UnsupportedOperationException("Paging not supported! Check first with supportsPaging()");
}
@Override
public void removeVersion(T element) throws StrolchPersistenceException {
throw new UnsupportedOperationException("Versioning is not supported!");