Skip to content

Commit

Permalink
Adds leftJoin to QueryBuilder.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincenzo Guzzi committed Oct 21, 2016
1 parent dae9c42 commit f0efa50
Showing 1 changed file with 67 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public class QueryBuilder<T> {

private final List<Object> values;
private final List<Join<T, ?>> joins;
private final List<Join<T, ?>> leftJoins;
private final AbstractDao<T, ?> dao;
private final String tablePrefix;

Expand All @@ -82,6 +83,7 @@ protected QueryBuilder(AbstractDao<T, ?> dao, String tablePrefix) {
this.tablePrefix = tablePrefix;
values = new ArrayList<Object>();
joins = new ArrayList<Join<T, ?>>();
leftJoins = new ArrayList<Join<T, ?>>();
whereCollector = new WhereCollector<T>(dao, tablePrefix);
stringOrderCollation = " COLLATE NOCASE";
}
Expand Down Expand Up @@ -205,6 +207,45 @@ public <J> Join<T, J> join(Join<?, T> sourceJoin, Property sourceProperty, Class
return addJoin(sourceJoin.tablePrefix, sourceProperty, destinationDao, destinationProperty);
}

/**
* Expands the query to another entity type by using a LEFT JOIN. The primary key property of the primary entity for
* this QueryBuilder is used to match the given destinationProperty.
*/
public <J> Join<T, J> leftJoin(Class<J> destinationEntityClass, Property destinationProperty) {
return leftJoin(dao.getPkProperty(), destinationEntityClass, destinationProperty);
}

/**
* Expands the query to another entity type by using a LEFT JOIN. The given sourceProperty is used to match the primary
* key property of the given destinationEntity.
*/
public <J> Join<T, J> leftJoin(Property sourceProperty, Class<J> destinationEntityClass) {
AbstractDao<J, ?> destinationDao = (AbstractDao<J, ?>) dao.getSession().getDao(destinationEntityClass);
Property destinationProperty = destinationDao.getPkProperty();
return addLeftJoin(tablePrefix, sourceProperty, destinationDao, destinationProperty);
}

/**
* Expands the query to another entity type by using a LEFT JOIN. The given sourceProperty is used to match the given
* destinationProperty of the given destinationEntity.
*/
public <J> Join<T, J> leftJoin(Property sourceProperty, Class<J> destinationEntityClass, Property destinationProperty) {
AbstractDao<J, ?> destinationDao = (AbstractDao<J, ?>) dao.getSession().getDao(destinationEntityClass);
return addLeftJoin(tablePrefix, sourceProperty, destinationDao, destinationProperty);
}

/**
* Expands the query to another entity type by using a LEFT JOIN. The given sourceJoin's property is used to match the
* given destinationProperty of the given destinationEntity. Note that destination entity of the given join is used
* as the source for the new join to add. In this way, it is possible to compose complex "join of joins" across
* several entities if required.
*/
public <J> Join<T, J> leftJoin(Join<?, T> sourceJoin, Property sourceProperty, Class<J> destinationEntityClass,
Property destinationProperty) {
AbstractDao<J, ?> destinationDao = (AbstractDao<J, ?>) dao.getSession().getDao(destinationEntityClass);
return addLeftJoin(sourceJoin.tablePrefix, sourceProperty, destinationDao, destinationProperty);
}

private <J> Join<T, J> addJoin(String sourceTablePrefix, Property sourceProperty, AbstractDao<J, ?> destinationDao,
Property destinationProperty) {
String joinTablePrefix = "J" + (joins.size() + 1);
Expand All @@ -214,6 +255,15 @@ private <J> Join<T, J> addJoin(String sourceTablePrefix, Property sourceProperty
return join;
}

private <J> Join<T, J> addLeftJoin(String sourceTablePrefix, Property sourceProperty, AbstractDao<J, ?> destinationDao,
Property destinationProperty) {
String joinTablePrefix = "LJ" + (leftJoins.size() + 1);
Join<T, J> join = new Join<T, J>(sourceTablePrefix, sourceProperty, destinationDao, destinationProperty,
joinTablePrefix);
leftJoins.add(join);
return join;
}

/** Adds the given properties to the ORDER BY section using ascending order. */
public QueryBuilder<T> orderAsc(Property... properties) {
orderAscOrDesc(" ASC", properties);
Expand Down Expand Up @@ -347,7 +397,7 @@ private int checkAddOffset(StringBuilder builder) {
* QueryBuilder for each execution.
*/
public DeleteQuery<T> buildDelete() {
if (!joins.isEmpty()) {
if (!joins.isEmpty() || !leftJoins.isEmpty()) {
throw new DaoException("JOINs are not supported for DELETE queries");
}
String tablename = dao.getTablename();
Expand Down Expand Up @@ -394,17 +444,27 @@ private void checkLog(String sql) {

private void appendJoinsAndWheres(StringBuilder builder, String tablePrefixOrNull) {
values.clear();
for (Join<T, ?> join : joins) {
builder.append(" JOIN ").append(join.daoDestination.getTablename()).append(' ');
builder.append(join.tablePrefix).append(" ON ");
SqlUtils.appendProperty(builder, join.sourceTablePrefix, join.joinPropertySource).append('=');
SqlUtils.appendProperty(builder, join.tablePrefix, join.joinPropertyDestination);
}
appendJoins(builder, joins, " JOIN ");
appendJoins(builder, leftJoins, " LEFT JOIN ");
boolean whereAppended = !whereCollector.isEmpty();
if (whereAppended) {
builder.append(" WHERE ");
whereCollector.appendWhereClause(builder, tablePrefixOrNull, values);
}
appendJoinWheres(builder, joins, whereAppended);
appendJoinWheres(builder, leftJoins, whereAppended);
}

private void appendJoins(StringBuilder builder, List<Join<T, ?>> joins, String joinType) {
for (Join<T, ?> join : joins) {
builder.append(joinType).append(join.daoDestination.getTablename()).append(' ');
builder.append(join.tablePrefix).append(" ON ");
SqlUtils.appendProperty(builder, join.sourceTablePrefix, join.joinPropertySource).append('=');
SqlUtils.appendProperty(builder, join.tablePrefix, join.joinPropertyDestination);
}
}

private void appendJoinWheres(StringBuilder builder, List<Join<T, ?>> joins, boolean whereAppended) {
for (Join<T, ?> join : joins) {
if (!join.whereCollector.isEmpty()) {
if (!whereAppended) {
Expand Down

0 comments on commit f0efa50

Please sign in to comment.