/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.fetchprofiles.join;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.UnknownProfileException;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.SessionImplementor;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Various tests related to join-style fetch profiles.
*
* @author Steve Ebersole
*/
public class JoinFetchProfileTest extends BaseCoreFunctionalTestCase {
public String[] getMappings() {
return new String[] { "fetchprofiles/join/Mappings.hbm.xml" };
}
public String getCacheConcurrencyStrategy() {
return null;
}
public void configure(Configuration cfg) {
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
}
@SuppressWarnings( {"UnusedDeclaration"})
private static interface TestData {
public Long getStudentId();
public Long getDepartmentId();
public Long getCourseId();
public Long getSectionId();
public Long getEnrollmentId();
}
private interface TestCode {
public void perform(TestData data);
}
@SuppressWarnings( {"unchecked"})
private void performWithStandardData(TestCode testCode) {
Session session = openSession();
session.beginTransaction();
final Department literatureDepartment = new Department( "lit", "Literature" );
session.save( literatureDepartment );
final Course lit101 = new Course( new Course.Code( literatureDepartment, 101 ), "Introduction to Literature" );
session.save( lit101 );
final CourseOffering section = new CourseOffering( lit101, 1, 2008 );
session.save( section );
final Student me = new Student( "Steve" );
session.save( me );
final Enrollment enrollment = new Enrollment( section, me );
section.getEnrollments().add( enrollment );
session.save( enrollment );
session.getTransaction().commit();
session.close();
sessionFactory().getStatistics().clear();
testCode.perform(
new TestData() {
public Long getStudentId() {
return me.getId();
}
public Long getDepartmentId() {
return literatureDepartment.getId();
}
public Long getCourseId() {
return lit101.getId();
}
public Long getSectionId() {
return section.getId();
}
public Long getEnrollmentId() {
return enrollment.getId();
}
}
);
session = openSession();
session.beginTransaction();
session.delete( enrollment );
session.delete( me );
session.delete( enrollment.getOffering() );
session.delete( enrollment.getOffering().getCourse() );
session.delete( enrollment.getOffering().getCourse().getCode().getDepartment() );
session.getTransaction().commit();
session.close();
}
@Test
public void testNormalLoading() {
performWithStandardData(
new TestCode() {
public void perform(TestData data) {
Session session = openSession();
session.beginTransaction();
CourseOffering section = ( CourseOffering ) session.get( CourseOffering.class, data.getSectionId() );
assertEquals( 1, sessionFactory().getStatistics().getEntityLoadCount() );
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
assertFalse( Hibernate.isInitialized( section.getCourse() ) );
assertFalse( Hibernate.isInitialized( section.getEnrollments() ) );
assertFalse( Hibernate.isInitialized( section.getCourse().getCode().getDepartment() ) );
assertTrue( Hibernate.isInitialized( section.getCourse() ) );
assertEquals( 1, sessionFactory().getStatistics().getEntityFetchCount() );
session.getTransaction().commit();
session.close();
}
}
);
}
@Test
public void testNormalCriteria() {
performWithStandardData(
new TestCode() {
public void perform(TestData data) {
Session session = openSession();
session.beginTransaction();
CourseOffering section = ( CourseOffering ) session.createCriteria( CourseOffering.class ).uniqueResult();
assertEquals( 1, sessionFactory().getStatistics().getEntityLoadCount() );
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
assertFalse( Hibernate.isInitialized( section.getCourse() ) );
assertFalse( Hibernate.isInitialized( section.getEnrollments() ) );
assertFalse( Hibernate.isInitialized( section.getCourse().getCode().getDepartment() ) );
assertTrue( Hibernate.isInitialized( section.getCourse() ) );
assertEquals( 1, sessionFactory().getStatistics().getEntityFetchCount() );
session.getTransaction().commit();
session.close();
}
}
);
}
@Test
public void testBasicFetchProfileOperation() {
assertTrue( "fetch profile not parsed properly", sessionFactory().containsFetchProfileDefinition( "enrollment.details" ) );
assertTrue( "fetch profile not parsed properly", sessionFactory().containsFetchProfileDefinition( "offering.details" ) );
assertTrue( "fetch profile not parsed properly", sessionFactory().containsFetchProfileDefinition( "course.details" ) );
Session s = openSession();
SessionImplementor si = ( SessionImplementor ) s;
s.enableFetchProfile( "enrollment.details" );
assertTrue( si.getLoadQueryInfluencers().hasEnabledFetchProfiles() );
s.disableFetchProfile( "enrollment.details" );
assertFalse( si.getLoadQueryInfluencers().hasEnabledFetchProfiles() );
try {
s.enableFetchProfile( "never-gonna-get-it" );
fail( "expecting failure on undefined fetch-profile" );
}
catch ( UnknownProfileException expected ) {
}
s.close();
}
@Test
public void testLoadManyToOneFetchProfile() {
performWithStandardData(
new TestCode() {
public void perform(TestData data) {
Session session = openSession();
session.beginTransaction();
session.enableFetchProfile( "enrollment.details" );
Enrollment enrollment = ( Enrollment ) session.get( Enrollment.class, data.getEnrollmentId() );
assertEquals( 3, sessionFactory().getStatistics().getEntityLoadCount() ); // enrollment + (section + student)
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
assertTrue( Hibernate.isInitialized( enrollment.getOffering() ) );
assertTrue( Hibernate.isInitialized( enrollment.getStudent() ) );
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
session.getTransaction().commit();
session.close();
}
}
);
}
@Test
public void testCriteriaManyToOneFetchProfile() {
performWithStandardData(
new TestCode() {
public void perform(TestData data) {
Session session = openSession();
session.beginTransaction();
session.enableFetchProfile( "enrollment.details" );
Enrollment enrollment = ( Enrollment ) session.createCriteria( Enrollment.class ).uniqueResult();
assertEquals( 3, sessionFactory().getStatistics().getEntityLoadCount() ); // enrollment + (section + student)
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
assertTrue( Hibernate.isInitialized( enrollment.getOffering() ) );
assertTrue( Hibernate.isInitialized( enrollment.getStudent() ) );
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
session.getTransaction().commit();
session.close();
}
}
);
}
@Test
public void testLoadOneToManyFetchProfile() {
performWithStandardData(
new TestCode() {
public void perform(TestData data) {
Session session = openSession();
session.beginTransaction();
session.enableFetchProfile( "offering.details" );
CourseOffering section = ( CourseOffering ) session.get( CourseOffering.class, data.getSectionId() );
assertEquals( 3, sessionFactory().getStatistics().getEntityLoadCount() ); // section + (enrollments + course)
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
assertTrue( Hibernate.isInitialized( section.getEnrollments() ) );
session.getTransaction().commit();
session.close();
}
}
);
}
@Test
public void testLoadDeepFetchProfile() {
performWithStandardData(
new TestCode() {
public void perform(TestData data) {
Session session = openSession();
session.beginTransaction();
// enable both enrollment and offering detail profiles;
// then loading the section/offering should fetch the enrollment
// which in turn should fetch student (+ offering).
session.enableFetchProfile( "offering.details" );
session.enableFetchProfile( "enrollment.details" );
CourseOffering section = ( CourseOffering ) session.get( CourseOffering.class, data.getSectionId() );
assertEquals( 4, sessionFactory().getStatistics().getEntityLoadCount() ); // section + (course + enrollments + (student))
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
assertTrue( Hibernate.isInitialized( section.getEnrollments() ) );
session.getTransaction().commit();
session.close();
}
}
);
}
@Test
public void testLoadComponentDerefFetchProfile() {
performWithStandardData(
new TestCode() {
public void perform(TestData data) {
Session session = openSession();
session.beginTransaction();
session.enableFetchProfile( "course.details" );
Course course = ( Course ) session.get( Course.class, data.getCourseId() );
assertEquals( 2, sessionFactory().getStatistics().getEntityLoadCount() ); // course + department
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
assertTrue( Hibernate.isInitialized( course.getCode().getDepartment() ) );
session.getTransaction().commit();
session.close();
}
}
);
}
/**
* fetch-profiles should have no effect what-so-ever on the direct results of the HQL query.
*
* TODO : this is actually not strictly true. what we should have happen is to subsequently load those fetches
*/
@Test
public void testHQL() {
performWithStandardData(
new TestCode() {
public void perform(TestData data) {
Session session = openSession();
session.beginTransaction();
session.enableFetchProfile( "offering.details" );
session.enableFetchProfile( "enrollment.details" );
List sections = session.createQuery( "from CourseOffering" ).list();
int sectionCount = sections.size();
assertEquals( "unexpected CourseOffering count", 1, sectionCount );
assertEquals( 1, sessionFactory().getStatistics().getEntityLoadCount() );
assertEquals( 0, sessionFactory().getStatistics().getEntityFetchCount() );
session.getTransaction().commit();
session.close();
}
}
);
}
}