Skip to content

Commit

Permalink
Allow Join type to be settable, fix #54
Browse files Browse the repository at this point in the history
  • Loading branch information
minborg committed Sep 4, 2020
1 parent cda18f1 commit 1cb2b25
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.speedment.jpastreamer.streamconfiguration.StreamConfiguration;
import org.junit.jupiter.api.Test;

import javax.persistence.criteria.JoinType;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
Expand Down Expand Up @@ -162,12 +163,12 @@ public Class<T> entityClass() {
}

@Override
public Set<Field<T>> joins() {
public Set<JoinConfiguration<T>> joins() {
return new HashSet<>();
}

@Override
public StreamConfiguration<T> joining(Field<T> field) {
public StreamConfiguration<T> joining(Field<T> field, JoinType joinType) {
throw new UnsupportedOperationException();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ public <T> RenderResult<?> render(final Pipeline<T> pipeline, final StreamConfig
criteria.getRoot().alias(pipeline.root().getSimpleName());
criteria.getQuery().select(criteria.getRoot());

streamConfiguration.joins().forEach(field -> criteria.getRoot().fetch(field.columnName(), JoinType.LEFT));
streamConfiguration.joins()
.forEach(joinConfiguration -> criteria.getRoot().fetch(joinConfiguration.field().columnName(), joinConfiguration.joinType()));

criteriaMerger.merge(pipeline, criteria);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.speedment.jpastreamer.streamconfiguration.standard.internal;

import com.speedment.jpastreamer.field.Field;
import com.speedment.jpastreamer.streamconfiguration.StreamConfiguration;

import javax.persistence.criteria.JoinType;

import static java.util.Objects.requireNonNull;

final class StandardJoinConfiguration<T> implements StreamConfiguration.JoinConfiguration<T> {

private final Field<T> field;
private final JoinType joinType;

StandardJoinConfiguration(final Field<T> field, final JoinType joinType) {
this.field = requireNonNull(field);
this.joinType = requireNonNull(joinType);
}

@Override
public Field<T> field() {
return field;
}

@Override
public JoinType joinType() {
return joinType;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

StandardJoinConfiguration<?> that = (StandardJoinConfiguration<?>) o;

if (!field.equals(that.field)) return false;
return joinType == that.joinType;
}

@Override
public int hashCode() {
int result = field.hashCode();
result = 31 * result + joinType.hashCode();
return result;
}

@Override
public String toString() {
return label(joinType) + " on " + field.columnName();
}

private static String label(final JoinType joinType) {
switch (joinType) {
case INNER: return "inner join";
case LEFT: return "left outer join";
case RIGHT: return "right outer join";
}
return joinType.name();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.speedment.jpastreamer.field.Field;
import com.speedment.jpastreamer.streamconfiguration.StreamConfiguration;

import javax.persistence.criteria.JoinType;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
Expand All @@ -25,16 +26,16 @@
public final class StandardStreamConfiguration<T> implements StreamConfiguration<T> {

private final Class<T> entityClass;
private final Set<Field<T>> joins;
private final Set<JoinConfiguration<T>> joinConfigurations;

public StandardStreamConfiguration(final Class<T> entityClass) {
this.entityClass = requireNonNull(entityClass);
this.joins = Collections.emptySet();
this.joinConfigurations = Collections.emptySet();
}

private StandardStreamConfiguration(final Class<T> entityClass, final Set<Field<T>> joins) {
private StandardStreamConfiguration(final Class<T> entityClass, final Set<JoinConfiguration<T>> joinConfigurations) {
this.entityClass = entityClass;
this.joins = new HashSet<>(joins);
this.joinConfigurations = new HashSet<>(joinConfigurations);
}

@Override
Expand All @@ -43,14 +44,16 @@ public Class<T> entityClass() {
}

@Override
public Set<Field<T>> joins() {
return Collections.unmodifiableSet(joins);
public Set<JoinConfiguration<T>> joins() {
return Collections.unmodifiableSet(joinConfigurations);
}

@Override
public StreamConfiguration<T> joining(Field<T> field) {
final Set<Field<T>> newjoins = new HashSet<>(joins);
newjoins.add(field);
public StreamConfiguration<T> joining(final Field<T> field, final JoinType joinType) {
requireNonNull(field);
requireNonNull(joinType);
final Set<JoinConfiguration<T>> newjoins = new HashSet<>(joinConfigurations);
newjoins.add(new StandardJoinConfiguration<>(field, joinType));
return new StandardStreamConfiguration<>(entityClass, newjoins);
}

Expand All @@ -62,21 +65,29 @@ public boolean equals(Object o) {
final StandardStreamConfiguration<?> that = (StandardStreamConfiguration<?>) o;

if (!entityClass.equals(that.entityClass)) return false;
return joins.equals(that.joins);
return joinConfigurations.equals(that.joinConfigurations);
}

@Override
public int hashCode() {
int result = entityClass.hashCode();
result = 31 * result + joins.hashCode();
result = 31 * result + joinConfigurations.hashCode();
return result;
}

@Override
public String toString() {

final String joinText = joinConfigurations.isEmpty()
? ""
: " joining " + joinConfigurations.stream()
.map(Object::toString)
.sorted()
.collect(Collectors.joining(", "));

return "StandardStreamConfiguration{" +
"of " + entityClass.getSimpleName() +
" joining " + joins.stream().map(Field::columnName).sorted().collect(Collectors.joining(", ")) +
joinText +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
*/
package com.speedment.jpastreamer.streamconfiguration.standard.internal;

import com.speedment.jpastreamer.field.Field;
import com.speedment.jpastreamer.streamconfiguration.StreamConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import javax.persistence.criteria.JoinType;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -40,9 +42,13 @@ void entityClass() {
@Test
void joins() {
final StreamConfiguration<Film> j1 = initial.joining(Film$.title);
assertEquals(Collections.singleton(Film$.title), j1.joins());
assertEquals(Collections.singleton(new StandardJoinConfiguration<>(Film$.title, JoinType.LEFT)), j1.joins());
final StreamConfiguration<Film> j2 = j1.joining(Film$.length);
assertEquals(Stream.of(Film$.title, Film$.length).collect(Collectors.toSet()), j2.joins());
final Set<StreamConfiguration.JoinConfiguration<Film>> excpected = Stream.<Field<Film>>of(Film$.title, Film$.length)
.map(f -> new StandardJoinConfiguration<>(f, JoinType.LEFT))
.collect(Collectors.toSet());

assertEquals(excpected, j2.joins());
assertNotSame(j1, j2);
}

Expand All @@ -67,5 +73,6 @@ void testToString() {
assertTrue(toString.contains(Film.class.getSimpleName()));
assertTrue(toString.contains(Film$.title.columnName()));
assertTrue(toString.contains(Film$.length.columnName()));
System.out.println(toString);
}
}
5 changes: 5 additions & 0 deletions streamconfiguration/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
<artifactId>field</artifactId>
</dependency>

<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.speedment.jpastreamer.field.Field;
import com.speedment.jpastreamer.rootfactory.RootFactory;

import javax.persistence.criteria.JoinType;
import java.util.ServiceLoader;
import java.util.Set;

Expand Down Expand Up @@ -49,31 +50,43 @@ public interface StreamConfiguration<T> {
* @return the fields that shall be joined in
* a future stream
*/
Set<Field<T>> joins();
Set<JoinConfiguration<T>> joins();

/**
* Creates and returns a new StreamConfiguration configured with
* the provided {@code field} so that it will be
* eagerly joined when producing elements in the future Stream.
* eagerly joined when producing elements in the future Stream
* using {@link JoinType#LEFT}.
* <p>
* This prevents the N+1 problem if the field is accessed in
* elements in the future Stream.
* </p>
* @param field to join
* @return this StreamConfigurationBuilder
* @return a new StreamConfiguration configured with
* the provided {@code field} so that it will be
* eagerly joined when producing elements in the future Stream
* using {@link JoinType#LEFT}
*/
StreamConfiguration<T> joining(Field<T> field);

// BEGIN: Mandates implementation
@Override
int hashCode();

@Override
boolean equals(Object obj);
default StreamConfiguration<T> joining(Field<T> field) {
return joining(field, JoinType.LEFT);
}

@Override
String toString();
// END: Mandates implementation
/**
* Creates and returns a new StreamConfiguration configured with
* the provided {@code field} so that it will be
* eagerly joined when producing elements in the future Stream
* using the provided {@code joinType}.
* <p>
* This prevents the N+1 problem if the field is accessed in
* elements in the future Stream.
* </p>
* @param field to join
* @return a new StreamConfiguration configured with
* the provided {@code field} so that it will be
* eagerly joined when producing elements in the future Stream
* using the provided {@code joinType}
*/
StreamConfiguration<T> joining(Field<T> field, JoinType joinType);

/**
* Creates and returns a new StreamConfiguration that can be used
Expand All @@ -95,4 +108,9 @@ static <T> StreamConfiguration<T> of(final Class<T> entityClass) {

}

interface JoinConfiguration<T> {
Field<T> field();
JoinType joinType();
}

}
1 change: 1 addition & 0 deletions streamconfiguration/src/main/java9/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
module jpastreamer.streamconfiguration {
requires transitive jpastreamer.field;
requires transitive java.persistence;
requires jpastreamer.rootfactory;

exports com.speedment.jpastreamer.streamconfiguration;
Expand Down

0 comments on commit 1cb2b25

Please sign in to comment.