Skip to content

Commit

Permalink
Adding support for LEFT OUTER JOIN...ON queries and upgrading the
Browse files Browse the repository at this point in the history
Hibernate version used in the Hibernate legacy version.
  • Loading branch information
Ming committed Apr 23, 2016
1 parent 1bf4e95 commit 326426e
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.jinq.jpa.transform.LimitSkipTransform;
import org.jinq.jpa.transform.MetamodelUtil;
import org.jinq.jpa.transform.MultiAggregateTransform;
import org.jinq.jpa.transform.OuterJoinOnTransform;
import org.jinq.jpa.transform.OuterJoinTransform;
import org.jinq.jpa.transform.QueryTransformException;
import org.jinq.jpa.transform.SelectTransform;
Expand All @@ -43,7 +44,9 @@
import org.jinq.orm.internal.QueryComposer;
import org.jinq.orm.stream.JinqStream.AggregateGroup;
import org.jinq.orm.stream.JinqStream.JoinToIterable;
import org.jinq.orm.stream.JinqStream.JoinWithSource;
import org.jinq.orm.stream.JinqStream.Select;
import org.jinq.orm.stream.JinqStream.WhereForOn;
import org.jinq.orm.stream.NextOnlyIterator;
import org.jinq.tuples.Pair;
import org.jinq.tuples.Tuple;
Expand Down Expand Up @@ -297,6 +300,43 @@ public <U> HibernateQueryComposer<U> applyTransformWithLambda(JPQLOneLambdaQuery
return new HibernateQueryComposer<>(this, (JPQLQuery<U>)cachedQuery.get(), lambdas, lambdaInfo);
}

public <U> HibernateQueryComposer<U> applyTransformWithTwoLambdas(OuterJoinOnTransform transform, Object lambda1, Object lambda2)
{
LambdaInfo lambdaInfo1 = lambdaAnalyzer.extractSurfaceInfo(lambda1, lambdas.size(), hints.dieOnError);
if (lambdaInfo1 == null) { translationFail(); return null; }
LambdaInfo lambdaInfo2 = lambdaAnalyzer.extractSurfaceInfo(lambda2, lambdas.size() + 1, hints.dieOnError);
if (lambdaInfo2 == null) { translationFail(); return null; }
Optional<JPQLQuery<?>> cachedQuery = hints.useCaching ?
cachedQueries.findInCache(query, transform.getTransformationTypeCachingTag(), new String[] {lambdaInfo1.getLambdaSourceString(), lambdaInfo2.getLambdaSourceString()}) : null;
if (cachedQuery == null)
{
cachedQuery = Optional.empty();
JPQLQuery<U> newQuery = null;
try {
LambdaAnalysis lambdaAnalysis1 = lambdaInfo1.fullyAnalyze(metamodel, hints.lambdaClassLoader, hints.isObjectEqualsSafe, hints.isAllEqualsSafe, hints.isCollectionContainsSafe, hints.dieOnError);
if (lambdaAnalysis1 == null) { translationFail(); return null; }
LambdaAnalysis lambdaAnalysis2 = lambdaInfo2.fullyAnalyze(metamodel, hints.lambdaClassLoader, hints.isObjectEqualsSafe, hints.isAllEqualsSafe, hints.isCollectionContainsSafe, hints.dieOnError);
if (lambdaAnalysis2 == null) { translationFail(); return null; }
getConfig().checkLambdaSideEffects(lambdaAnalysis1);
getConfig().checkLambdaSideEffects(lambdaAnalysis2);
newQuery = transform.apply(query, lambdaAnalysis1, lambdaAnalysis2, null);
}
catch (QueryTransformException e)
{
translationFail(e);
}
finally
{
// Always cache the resulting query, even if it is an error
cachedQuery = Optional.ofNullable(newQuery);
if (hints.useCaching)
cachedQuery = cachedQueries.cacheQuery(query, transform.getTransformationTypeCachingTag(), new String[] {lambdaInfo1.getLambdaSourceString(), lambdaInfo2.getLambdaSourceString()}, cachedQuery);
}
}
if (!cachedQuery.isPresent()) { translationFail(); return null; }
return new HibernateQueryComposer<>(this, (JPQLQuery<U>)cachedQuery.get(), lambdas, lambdaInfo1, lambdaInfo2);
}

public <U> HibernateQueryComposer<U> applyTransformWithLambdas(JPQLMultiLambdaQueryTransform transform, Object [] groupingLambdas)
{
LambdaInfo[] lambdaInfos = new LambdaInfo[groupingLambdas.length];
Expand Down Expand Up @@ -484,7 +524,14 @@ public <U> QueryComposer<T> leftOuterJoinFetchIterable(
{
return applyTransformWithLambda(new JoinFetchTransform(getConfig()).setIsExpectingStream(false).setIsOuterJoinFetch(true), joinLambda);
}


@Override
public <U> QueryComposer<Pair<T, U>> leftOuterJoinWithSource(
JoinWithSource<T, U> join, WhereForOn<T, U> on)
{
return applyTransformWithTwoLambdas(new OuterJoinOnTransform(getConfig()).setIsExpectingStream(true), join, on);
}

@Override
public Long count()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ public <U> JPAJinqStream<Pair<T, U>> leftOuterJoinList(
return wrap(wrapped.leftOuterJoinList(join));
}

@Override
public <U> JPAJinqStream<Pair<T, U>> leftOuterJoin(
org.jinq.orm.stream.JinqStream.JoinWithSource<T, U> join,
org.jinq.orm.stream.JinqStream.WhereForOn<T, U> on)
{
return wrap(wrapped.leftOuterJoin(join, on));
}

@Override
public <U, V> JPAJinqStream<Pair<U, V>> group(
org.jinq.orm.stream.JinqStream.Select<T, U> select,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@ public <U> JPAJinqStream<Pair<T, U>> leftOuterJoinList(
return wrap(super.leftOuterJoinList(join));
}

@Override
public <U> JPAJinqStream<Pair<T, U>> leftOuterJoin(
org.jinq.orm.stream.JinqStream.JoinWithSource<T, U> join,
org.jinq.orm.stream.JinqStream.WhereForOn<T, U> on)
{
return wrap(super.leftOuterJoin(join, on));
}

@Override
public <U, V> JPAJinqStream<Pair<U, V>> group(
org.jinq.orm.stream.JinqStream.Select<T, U> select,
Expand Down
2 changes: 1 addition & 1 deletion jinq-hibernate-legacy/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.10.Final</version>
<version>5.1.0.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
Expand Down
51 changes: 51 additions & 0 deletions jinq-hibernate-legacy/test/org/jinq/hibernate/JinqJPATest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.jinq.orm.stream.JinqStream.Where;
import org.jinq.orm.stream.QueryJinqStream;
import org.jinq.tuples.Pair;
import org.junit.Assert;
import org.junit.Test;

public class JinqJPATest extends JinqJPATestBase
Expand Down Expand Up @@ -211,6 +212,56 @@ public void testOuterJoin11()
assertEquals(1, results.size());
}


@Test
public void testOuterJoinOn()
{
List<Pair<Item, Supplier>> results = streams.streamAll(em, Item.class)
.leftOuterJoin(
(i, source) -> source.stream(Supplier.class),
(item, supplier) -> item.getName().substring(0, 1).equals(supplier.getName().substring(0, 1)))
.toList();
assertEquals("SELECT A, B FROM org.jinq.hibernate.test.entities.Item A LEFT OUTER JOIN org.jinq.hibernate.test.entities.Supplier B ON SUBSTRING(A.name, 0 + 1, 1 - 0) = SUBSTRING(B.name, 0 + 1, 1 - 0)", query);
Collections.sort(results, (c1, c2) -> c1.getOne().getName().compareTo(c2.getOne().getName()));
assertEquals(5, results.size());
assertEquals("Lawnmowers", results.get(0).getOne().getName());
Assert.assertNull(results.get(0).getTwo());
assertEquals("Talent", results.get(2).getOne().getName());
assertEquals("Talent Agency", results.get(2).getTwo().getName());
}

@Test
public void testOuterJoinOnTrueAndNavigationalLinks()
{
List<Pair<Item, Supplier>> results = streams.streamAll(em, Item.class)
.leftOuterJoin(
(i, source) -> JinqStream.from(i.getSuppliers()),
(item, supplier) -> true)
.toList();
assertEquals("SELECT A, B FROM org.jinq.hibernate.test.entities.Item A LEFT OUTER JOIN A.suppliers B", query);
assertEquals(6, results.size());
}

@Test
public void testOuterJoinOnWithParametersAndIndirect()
{
String match = "Screws";
List<Pair<String, Supplier>> results = streams.streamAll(em, Item.class)
.select(i -> i.getName())
.leftOuterJoin(
(i, source) -> source.stream(Supplier.class),
(itemName, supplier) -> itemName.equals(match))
.toList();
assertEquals("SELECT A.name, B FROM org.jinq.hibernate.test.entities.Item A LEFT OUTER JOIN org.jinq.hibernate.test.entities.Supplier B ON A.name = :param0", query);
Collections.sort(results, (c1, c2) -> c1.getOne().compareTo(c2.getOne()));
assertEquals(7, results.size());
assertEquals("Lawnmowers", results.get(0).getOne());
Assert.assertNull(results.get(0).getTwo());
assertEquals("Screws", results.get(1).getOne());
assertEquals("Screws", results.get(2).getOne());
assertEquals("Screws", results.get(3).getOne());
}

@Test
public void testOuterJoinFetch()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ public class JinqJPATestBase
public static void setUpBeforeClass() throws Exception
{
Configuration configuration = new Configuration().configure("META-INF/hibernate.cfg.xml");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
// ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
// .applySettings(configuration.getProperties())
// .build();
// sessionFactory = configuration.buildSessionFactory(serviceRegistry);
// Hibernate keeps changing how it's configured. The old way no longer works, apparently.
sessionFactory = configuration.buildSessionFactory();
streams = new JinqHibernateStreamProvider(sessionFactory);

// Hibernate's ClassMetadata doesn't have as much information as the Criteria API
Expand Down
5 changes: 5 additions & 0 deletions jinq-jpa/main/org/jinq/jpa/JPAJinqStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ public interface JPAJinqStream<T> extends JinqStream<T>
@Override
public <U> JPAJinqStream<Pair<T, U>> leftOuterJoinList(JoinToIterable<T, U> join);

@Override
public <U> JPAJinqStream<Pair<T, U>> leftOuterJoin(
JinqStream.JoinWithSource<T, U> join,
JinqStream.WhereForOn<T, U> on);

@Override
public <U, V> JPAJinqStream<Pair<U, V>> group(Select<T, U> select,
AggregateGroup<U, T, V> aggregate);
Expand Down
2 changes: 1 addition & 1 deletion jinq-jpa/main/org/jinq/jpa/JPAJinqStreamWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public <U> JPAJinqStream<Pair<T, U>> leftOuterJoinList(
}

@Override
public <U> JinqStream<Pair<T, U>> leftOuterJoin(
public <U> JPAJinqStream<Pair<T, U>> leftOuterJoin(
org.jinq.orm.stream.JinqStream.JoinWithSource<T, U> join,
org.jinq.orm.stream.JinqStream.WhereForOn<T, U> on)
{
Expand Down
8 changes: 8 additions & 0 deletions jinq-jpa/main/org/jinq/jpa/QueryJPAJinqStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ public <U> JPAJinqStream<Pair<T, U>> leftOuterJoinList(
return wrap(super.leftOuterJoinList(join));
}

@Override
public <U> JPAJinqStream<Pair<T, U>> leftOuterJoin(
org.jinq.orm.stream.JinqStream.JoinWithSource<T, U> join,
org.jinq.orm.stream.JinqStream.WhereForOn<T, U> on)
{
return wrap(super.leftOuterJoin(join, on));
}

@Override
public <U, V> JPAJinqStream<Pair<U, V>> group(
org.jinq.orm.stream.JinqStream.Select<T, U> select,
Expand Down

0 comments on commit 326426e

Please sign in to comment.