/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.test.lob; import java.sql.Clob; import java.sql.SQLException; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Lob; import javax.persistence.Table; import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.dialect.SQLServerDialect; import org.hibernate.engine.jdbc.ClobProxy; import org.hibernate.query.Query; import org.hibernate.testing.SkipForDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.transaction.TransactionUtil; import org.junit.Test; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** * @author Andrea Boriero */ @TestForIssue(jiraKey = "HHH-11477") @SkipForDialect(Oracle8iDialect.class) public class LobStringTest extends BaseCoreFunctionalTestCase { //SQL Server - VARCHAR(MAX) is limited to 8000 bytes only private static final int LONG_STRING_SIZE = 3999; private final String value1 = buildRecursively( LONG_STRING_SIZE, 'x' ); private final String value2 = buildRecursively( LONG_STRING_SIZE, 'y' ); @Override protected Class<?>[] getAnnotatedClasses() { return new Class[] {TestEntity.class}; } @Override protected void prepareTest() throws Exception { TestEntity entity = new TestEntity(); TransactionUtil.doInHibernate( this::sessionFactory, session -> { entity.setFirstLobField( value1 ); entity.setSecondLobField( value2 ); entity.setClobField( session.getLobHelper().createClob( value2 ) ); session.save( entity ); } ); TransactionUtil.doInHibernate( this::sessionFactory, session -> { final TestEntity testEntity = session.find( TestEntity.class, entity.getId() ); assertThat( testEntity.getFirstLobField(), is( value1 ) ); } ); } @Test @TestForIssue(jiraKey = "HHH-11477") public void testHqlQuery() { TransactionUtil.doInHibernate( this::sessionFactory, session -> { final Query query = session.createQuery( "from TestEntity" ); final List<TestEntity> results = query.list(); assertThat( results.size(), is( 1 ) ); final TestEntity testEntity = results.get( 0 ); assertThat( testEntity.getFirstLobField(), is( value1 ) ); assertThat( testEntity.getSecondLobField(), is( value2 ) ); final Clob clobField = testEntity.getClobField(); try { assertThat( clobField.getSubString( 1, (int) clobField.length() ), is( value2 ) ); } catch (SQLException e) { fail( e.getMessage() ); } } ); } @Test @TestForIssue(jiraKey = "HHH-11477") public void testUsingStringLobAnnotatedPropertyInHqlQuery() { TransactionUtil.doInHibernate( this::sessionFactory, session -> { final Query query = session.createQuery( "from TestEntity where LOWER(firstLobField) LIKE :value" ); query.setParameter( "value", value1 ); final List<TestEntity> results = query.list(); assertThat( results.size(), is( 1 ) ); final TestEntity testEntity = results.get( 0 ); assertThat( testEntity.getFirstLobField(), is( value1 ) ); assertThat( testEntity.getSecondLobField(), is( value2 ) ); final Clob clobField = testEntity.getClobField(); try { assertThat( clobField.getSubString( 1, (int) clobField.length() ), is( value2 ) ); } catch (SQLException e) { fail( e.getMessage() ); } } ); } @Test @TestForIssue(jiraKey = "HHH-11477") public void testSelectStringLobAnnotatedInHqlQuery() { TransactionUtil.doInHibernate( this::sessionFactory, session -> { final Query query = session.createQuery( "select t.secondLobField from TestEntity t where LOWER(t.firstLobField) LIKE :value" ); query.setParameter( "value", value1 ); final List<String> results = query.list(); assertThat( results.size(), is( 1 ) ); assertThat( results.get( 0 ), is( value2 ) ); } ); } @Test @TestForIssue(jiraKey = "HHH-11477") public void testUsingLobPropertyInHqlQuery() { TransactionUtil.doInHibernate( this::sessionFactory, session -> { final Query query = session.createQuery( "select t.secondLobField from TestEntity t where LOWER(t.clobField) LIKE :value" ); query.setParameter( "value", ClobProxy.generateProxy( value2 ) ); final List<String> results = query.list(); assertThat( results.size(), is( 1 ) ); assertThat( results.get( 0 ), is( value2 ) ); } ); } @Test @TestForIssue(jiraKey = "HHH-11477") public void testSelectClobPropertyInHqlQuery() { TransactionUtil.doInHibernate( this::sessionFactory, session -> { final Query query = session.createQuery( "select t.clobField from TestEntity t where LOWER(t.clobField) LIKE :value" ); query.setParameter( "value", ClobProxy.generateProxy( value2 ) ); final List<Clob> results = query.list(); assertThat( results.size(), is( 1 ) ); final Clob clobField = results.get( 0 ); try { assertThat( clobField.getSubString( 1, (int) clobField.length() ), is( value2 ) ); } catch (SQLException e) { fail( e.getMessage() ); } } ); } @Entity(name = "TestEntity") @Table(name = "TEST_ENTITY") public static class TestEntity { @Id @GeneratedValue private long id; @Lob @Column(length = LONG_STRING_SIZE) //needed by HSQLDialect String firstLobField; @Lob @Column(length = LONG_STRING_SIZE) //needed by HSQLDialect String secondLobField; @Lob @Column(length = LONG_STRING_SIZE) //needed by HSQLDialect Clob clobField; public long getId() { return id; } public String getFirstLobField() { return firstLobField; } public void setFirstLobField(String firstLobField) { this.firstLobField = firstLobField; } public String getSecondLobField() { return secondLobField; } public void setSecondLobField(String secondLobField) { this.secondLobField = secondLobField; } public Clob getClobField() { return clobField; } public void setClobField(Clob clobField) { this.clobField = clobField; } } @Override protected boolean isCleanupTestDataRequired() { return true; } private String buildRecursively(int size, char baseChar) { StringBuilder buff = new StringBuilder(); for ( int i = 0; i < size; i++ ) { buff.append( baseChar ); } return buff.toString(); } }