/*
* Copyright 2014 - 2017 Blazebit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.blazebit.persistence.criteria;
import static org.junit.Assert.assertEquals;
import javax.persistence.criteria.JoinType;
import com.blazebit.persistence.testsuite.base.category.NoDatanucleus;
import com.googlecode.catchexception.CatchException;
import org.junit.Test;
import com.blazebit.persistence.CriteriaBuilder;
import com.blazebit.persistence.criteria.impl.BlazeCriteria;
import com.blazebit.persistence.testsuite.AbstractCoreTest;
import com.blazebit.persistence.testsuite.entity.Document;
import com.blazebit.persistence.testsuite.entity.Document_;
import com.blazebit.persistence.testsuite.entity.Person;
import com.blazebit.persistence.testsuite.entity.Person_;
import org.junit.experimental.categories.Category;
/**
*
* @author Christian Beikov
* @since 1.2.0
*/
public class JoinTest extends AbstractCoreTest {
@Test
public void joinTypesSingular() {
BlazeCriteriaQuery<Long> cq = BlazeCriteria.get(em, cbf, Long.class);
BlazeCriteriaBuilder cb = cq.getCriteriaBuilder();
BlazeRoot<Document> root = cq.from(Document.class, "document");
BlazeJoin<Document, Person> p1 = root.join(Document_.owner, "owner1", JoinType.INNER);
BlazeJoin<Document, Person> p2 = root.join(Document_.owner, "owner2", JoinType.LEFT);
// Right join is not supported
CatchException.verifyException(root, UnsupportedOperationException.class).join(Document_.owner, "owner3", JoinType.RIGHT);
BlazeJoin<Person, Document> p1_1 = p1.join(Person_.partnerDocument, "partnerDoc", JoinType.INNER);
cq.select(root.get(Document_.id));
CriteriaBuilder<?> criteriaBuilder = cq.createCriteriaBuilder();
assertEquals("SELECT document.id FROM Document document JOIN document.owner owner1 JOIN owner1.partnerDocument partnerDoc LEFT JOIN document.owner owner2", criteriaBuilder.getQueryString());
}
@Test
public void joinSet() {
BlazeCriteriaQuery<Long> cq = BlazeCriteria.get(em, cbf, Long.class);
BlazeCriteriaBuilder cb = cq.getCriteriaBuilder();
BlazeRoot<Document> root = cq.from(Document.class, "document");
BlazeJoin<Document, Person> partners = root.join(Document_.partners, "partner");
BlazeJoin<Person, Document> ownerDocuments = partners.join(Person_.ownedDocuments, "doc");
cq.select(root.get(Document_.id));
CriteriaBuilder<?> criteriaBuilder = cq.createCriteriaBuilder();
assertEquals("SELECT document.id FROM Document document JOIN document.partners partner JOIN partner.ownedDocuments doc", criteriaBuilder.getQueryString());
}
@Test
public void fetchSet() {
BlazeCriteriaQuery<Document> cq = BlazeCriteria.get(em, cbf, Document.class);
BlazeCriteriaBuilder cb = cq.getCriteriaBuilder();
BlazeRoot<Document> root = cq.from(Document.class, "document");
BlazeJoin<Document, Person> partners = root.fetch(Document_.partners, "partner");
BlazeJoin<Person, Document> ownerDocuments = partners.join(Person_.ownedDocuments, "doc");
ownerDocuments.fetch();
cq.select(root);
CriteriaBuilder<?> criteriaBuilder = cq.createCriteriaBuilder();
assertEquals("SELECT document FROM Document document JOIN FETCH document.partners partner JOIN FETCH partner.ownedDocuments doc", criteriaBuilder.getQueryString());
}
@Test
public void listMapJoinWithFunctions() {
BlazeCriteriaQuery<Long> cq = BlazeCriteria.get(em, cbf, Long.class);
BlazeCriteriaBuilder cb = cq.getCriteriaBuilder();
BlazeRoot<Document> root = cq.from(Document.class, "document");
BlazeListJoin<Document, Person> people = root.join(Document_.people, "person");
BlazeMapJoin<Document, Integer, Person> contacts = root.join(Document_.contacts, "contact");
BlazeMapJoin<Person, Integer, String> localized = people.join(Person_.localized, "localized");
BlazeJoin<Person, Document> partnerDocument = contacts.join(Person_.partnerDocument, "partnerDoc");
cq.multiselect(
people.index(),
contacts.key(),
contacts.value(),
contacts.entry()
);
CriteriaBuilder<?> criteriaBuilder = cq.createCriteriaBuilder();
assertEquals("SELECT INDEX(person), KEY(contact), " + joinAliasValue("contact") + ", ENTRY(contact) " +
"FROM Document document JOIN document.contacts contact JOIN contact.partnerDocument partnerDoc JOIN document.people person JOIN person.localized localized" +
"", criteriaBuilder.getQueryString());
}
@Test
// TODO: Report that SingularAttributeImpl#getBindableType() returns ENTITY_TYPE instead of SINGULAR_ATTRIBUTE
@Category(NoDatanucleus.class)
public void listStringMapEmbeddableJoinWithFunctions() {
BlazeCriteriaQuery<Long> cq = BlazeCriteria.get(em, cbf, Long.class);
BlazeCriteriaBuilder cb = cq.getCriteriaBuilder();
BlazeRoot<Document> root = cq.from(Document.class, "document");
BlazeListJoin<Document, Person> people = (BlazeListJoin<Document, Person>) (BlazeListJoin<?, ?>) root.join("people", "person");
BlazeMapJoin<Document, Integer, Person> contacts = (BlazeMapJoin<Document, Integer, Person>) (BlazeMapJoin<?, ?, ?>) root.join("contacts", "contact");
BlazeMapJoin<Person, Integer, String> localized = (BlazeMapJoin<Person, Integer, String>) (BlazeMapJoin<?, ?, ?>) people.join("localized", "localized");
BlazeJoin<Person, Document> partnerDocument = contacts.join("partnerDocument", "partnerDoc");
root.join("nameObject").join("intIdEntity", "intEntity");
cq.multiselect(
people.index(),
contacts.key(),
contacts.value(),
contacts.entry()
);
CriteriaBuilder<?> criteriaBuilder = cq.createCriteriaBuilder();
assertEquals("SELECT INDEX(person), KEY(contact), " + joinAliasValue("contact") + ", ENTRY(contact) " +
"FROM Document document JOIN document.contacts contact " +
"JOIN contact.partnerDocument partnerDoc " +
"JOIN document.nameObject.intIdEntity intEntity " +
"JOIN document.people person " +
"JOIN person.localized localized" +
"", criteriaBuilder.getQueryString());
}
@Test
public void joinsWithOnClause() {
BlazeCriteriaQuery<Long> cq = BlazeCriteria.get(em, cbf, Long.class);
BlazeCriteriaBuilder cb = cq.getCriteriaBuilder();
BlazeRoot<Document> root = cq.from(Document.class, "document");
BlazeJoin<Document, Person> partnerDocument = root.join(Document_.owner, "owner");
BlazeListJoin<Document, Person> people = root.join(Document_.people, "person");
BlazeMapJoin<Document, Integer, Person> contacts = root.join(Document_.contacts, "contact");
partnerDocument.on(partnerDocument.get(Person_.age).isNotNull());
people.on(people.index().isNotNull());
contacts.on(contacts.key().isNotNull());
cq.select(root.get(Document_.id));
CriteriaBuilder<?> criteriaBuilder = cq.createCriteriaBuilder();
assertEquals("SELECT document.id FROM Document document" +
" JOIN document.contacts contact"
+ onClause("KEY(contact) IS NOT NULL") +
" JOIN document.owner owner"
+ onClause("owner.age IS NOT NULL") +
" JOIN document.people person"
+ onClause("INDEX(person) IS NOT NULL"), criteriaBuilder.getQueryString());
}
}