Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds leftJoin to QueryBuilder. #506

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
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