mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-18 00:55:16 +00:00
Re-enabled additional tests
This commit is contained in:
parent
6745f71f88
commit
67c2c51d47
@ -9,17 +9,19 @@
|
|||||||
import java.sql.Clob;
|
import java.sql.Clob;
|
||||||
|
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.dialect.SybaseASEDialect;
|
import org.hibernate.dialect.SybaseASEDialect;
|
||||||
import org.hibernate.type.descriptor.java.DataHelper;
|
import org.hibernate.type.descriptor.java.DataHelper;
|
||||||
|
|
||||||
import org.hibernate.testing.DialectChecks;
|
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||||
import org.hibernate.testing.RequiresDialectFeature;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||||
import org.junit.Test;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests lazy materialization of data mapped by
|
* Tests lazy materialization of data mapped by
|
||||||
@ -29,133 +31,176 @@
|
|||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@RequiresDialectFeature(
|
@RequiresDialectFeature(
|
||||||
value = { DialectChecks.SupportsExpectedLobUsagePattern.class, DialectChecks.SupportsUnboundedLobLocatorMaterializationCheck.class },
|
feature = DialectFeatureChecks.SupportsExpectedLobUsagePattern.class,
|
||||||
comment = "database/driver does not support expected LOB usage pattern"
|
comment = "database/driver does not support expected LOB usage pattern"
|
||||||
)
|
)
|
||||||
public class ClobLocatorTest extends BaseCoreFunctionalTestCase {
|
@RequiresDialectFeature(
|
||||||
|
feature = DialectFeatureChecks.SupportsUnboundedLobLocatorMaterializationCheck.class,
|
||||||
|
comment = "database/driver does not support expected LOB usage pattern"
|
||||||
|
)
|
||||||
|
@DomainModel(
|
||||||
|
xmlMappings = "org/hibernate/orm/test/lob/LobMappings.hbm.xml"
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class ClobLocatorTest {
|
||||||
private static final int CLOB_SIZE = 10000;
|
private static final int CLOB_SIZE = 10000;
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getBaseForMappings() {
|
|
||||||
return "org/hibernate/orm/test/";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getMappings() {
|
public String[] getMappings() {
|
||||||
return new String[] { "lob/LobMappings.hbm.xml" };
|
return new String[] { "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBoundedClobLocatorAccess() throws Throwable {
|
public void testBoundedClobLocatorAccess(SessionFactoryScope scope) throws Throwable {
|
||||||
String original = buildString( CLOB_SIZE, 'x' );
|
String original = buildString( CLOB_SIZE, 'x' );
|
||||||
String changed = buildString( CLOB_SIZE, 'y' );
|
String changed = buildString( CLOB_SIZE, 'y' );
|
||||||
String empty = "";
|
String empty = "";
|
||||||
|
|
||||||
Session s = openSession();
|
Long id = scope.fromTransaction(
|
||||||
s.beginTransaction();
|
session -> {
|
||||||
LobHolder entity = new LobHolder();
|
LobHolder entity = new LobHolder();
|
||||||
entity.setClobLocator( s.getLobHelper().createClob( original ) );
|
entity.setClobLocator( session.getLobHelper().createClob( original ) );
|
||||||
s.save( entity );
|
session.save( entity );
|
||||||
s.getTransaction().commit();
|
return entity.getId();
|
||||||
s.close();
|
}
|
||||||
|
);
|
||||||
|
|
||||||
s = openSession();
|
scope.inTransaction(
|
||||||
s.beginTransaction();
|
session -> {
|
||||||
entity = s.get( LobHolder.class, entity.getId() );
|
try {
|
||||||
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
LobHolder entity = session.get( LobHolder.class, id );
|
||||||
assertEquals( original, extractData( entity.getClobLocator() ) );
|
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
||||||
s.getTransaction().commit();
|
assertEquals( original, extractData( entity.getClobLocator() ) );
|
||||||
s.close();
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// test mutation via setting the new clob data...
|
// test mutation via setting the new clob data...
|
||||||
if ( getDialect().supportsLobValueChangePropagation() ) {
|
if ( scope.getSessionFactory().getJdbcServices().getDialect().supportsLobValueChangePropagation() ) {
|
||||||
s = openSession();
|
scope.inTransaction(
|
||||||
s.beginTransaction();
|
session -> {
|
||||||
entity = ( LobHolder ) s.byId( LobHolder.class ).with( LockOptions.UPGRADE ).load( entity.getId() );
|
try {
|
||||||
entity.getClobLocator().truncate( 1 );
|
LobHolder entity = session.byId( LobHolder.class )
|
||||||
entity.getClobLocator().setString( 1, changed );
|
.with( LockOptions.UPGRADE )
|
||||||
s.getTransaction().commit();
|
.load( id );
|
||||||
s.close();
|
entity.getClobLocator().truncate( 1 );
|
||||||
|
entity.getClobLocator().setString( 1, changed );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
s = openSession();
|
scope.inTransaction(
|
||||||
s.beginTransaction();
|
session -> {
|
||||||
entity = ( LobHolder ) s.byId( LobHolder.class ).with( LockOptions.UPGRADE ).load( entity.getId() );
|
try {
|
||||||
assertNotNull( entity.getClobLocator() );
|
LobHolder entity = session.byId( LobHolder.class )
|
||||||
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
.with( LockOptions.UPGRADE )
|
||||||
assertEquals( changed, extractData( entity.getClobLocator() ) );
|
.load( id );
|
||||||
entity.getClobLocator().truncate( 1 );
|
assertNotNull( entity.getClobLocator() );
|
||||||
entity.getClobLocator().setString( 1, original );
|
|
||||||
s.getTransaction().commit();
|
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
||||||
s.close();
|
|
||||||
|
assertEquals( changed, extractData( entity.getClobLocator() ) );
|
||||||
|
entity.getClobLocator().truncate( 1 );
|
||||||
|
entity.getClobLocator().setString( 1, original );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test mutation via supplying a new clob locator instance...
|
// test mutation via supplying a new clob locator instance...
|
||||||
s = openSession();
|
scope.inTransaction(
|
||||||
s.beginTransaction();
|
session -> {
|
||||||
entity = ( LobHolder ) s.byId( LobHolder.class ).with( LockOptions.UPGRADE ).load( entity.getId() );
|
try {
|
||||||
assertNotNull( entity.getClobLocator() );
|
LobHolder entity = session.byId( LobHolder.class ).with( LockOptions.UPGRADE ).load( id );
|
||||||
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
assertNotNull( entity.getClobLocator() );
|
||||||
assertEquals( original, extractData( entity.getClobLocator() ) );
|
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
||||||
entity.setClobLocator( s.getLobHelper().createClob( changed ) );
|
assertEquals( original, extractData( entity.getClobLocator() ) );
|
||||||
s.getTransaction().commit();
|
entity.setClobLocator( session.getLobHelper().createClob( changed ) );
|
||||||
s.close();
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// test empty clob
|
// test empty clob
|
||||||
if ( !(getDialect() instanceof SybaseASEDialect ) ) { // Skip for Sybase. HHH-6425
|
if ( !( scope.getSessionFactory()
|
||||||
s = openSession();
|
.getJdbcServices()
|
||||||
s.beginTransaction();
|
.getDialect() instanceof SybaseASEDialect ) ) { // Skip for Sybase. HHH-6425
|
||||||
entity = s.get( LobHolder.class, entity.getId() );
|
scope.inTransaction(
|
||||||
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
session -> {
|
||||||
assertEquals( changed, extractData( entity.getClobLocator() ) );
|
try {
|
||||||
entity.setClobLocator( s.getLobHelper().createClob( empty ) );
|
LobHolder entity = session.get( LobHolder.class, id );
|
||||||
s.getTransaction().commit();
|
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
||||||
s.close();
|
assertEquals( changed, extractData( entity.getClobLocator() ) );
|
||||||
|
entity.setClobLocator( session.getLobHelper().createClob( empty ) );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
s = openSession();
|
scope.inTransaction(
|
||||||
s.beginTransaction();
|
session -> {
|
||||||
entity = s.get( LobHolder.class, entity.getId() );
|
try {
|
||||||
if ( entity.getClobLocator() != null) {
|
LobHolder entity = session.get( LobHolder.class, id );
|
||||||
assertEquals( empty.length(), entity.getClobLocator().length() );
|
if ( entity.getClobLocator() != null ) {
|
||||||
assertEquals( empty, extractData( entity.getClobLocator() ) );
|
assertEquals( empty.length(), entity.getClobLocator().length() );
|
||||||
}
|
assertEquals( empty, extractData( entity.getClobLocator() ) );
|
||||||
s.delete( entity );
|
}
|
||||||
s.getTransaction().commit();
|
session.delete( entity );
|
||||||
s.close();
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnboundedClobLocatorAccess() throws Throwable {
|
public void testUnboundedClobLocatorAccess(SessionFactoryScope scope) throws Throwable {
|
||||||
// Note: unbounded mutation of the underlying lob data is completely
|
// Note: unbounded mutation of the underlying lob data is completely
|
||||||
// unsupported; most databases would not allow such a construct anyway.
|
// unsupported; most databases would not allow such a construct anyway.
|
||||||
// Thus here we are only testing materialization...
|
// Thus here we are only testing materialization...
|
||||||
|
|
||||||
String original = buildString( CLOB_SIZE, 'x' );
|
String original = buildString( CLOB_SIZE, 'x' );
|
||||||
|
|
||||||
Session s = openSession();
|
Long id = scope.fromTransaction(
|
||||||
s.beginTransaction();
|
session -> {
|
||||||
LobHolder entity = new LobHolder();
|
LobHolder entity = new LobHolder();
|
||||||
entity.setClobLocator( s.getLobHelper().createClob( original ) );
|
entity.setClobLocator( session.getLobHelper().createClob( original ) );
|
||||||
s.save( entity );
|
session.save( entity );
|
||||||
s.getTransaction().commit();
|
return entity.getId();
|
||||||
s.close();
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// load the entity with the clob locator, and close the session/transaction;
|
// load the entity with the clob locator, and close the session/transaction;
|
||||||
// at that point it is unbounded...
|
// at that point it is unbounded...
|
||||||
s = openSession();
|
LobHolder lobHolder = scope.fromTransaction(
|
||||||
s.beginTransaction();
|
session ->
|
||||||
entity = s.get( LobHolder.class, entity.getId() );
|
session.get( LobHolder.class, id )
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
|
);
|
||||||
assertEquals( original, extractData( entity.getClobLocator() ) );
|
|
||||||
|
|
||||||
s = openSession();
|
assertEquals( CLOB_SIZE, lobHolder.getClobLocator().length() );
|
||||||
s.beginTransaction();
|
assertEquals( original, extractData( lobHolder.getClobLocator() ) );
|
||||||
s.delete( entity );
|
|
||||||
s.getTransaction().commit();
|
scope.inTransaction(
|
||||||
s.close();
|
session ->
|
||||||
|
session.delete( lobHolder )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String extractData(Clob clob) throws Exception {
|
public static String extractData(Clob clob) throws Exception {
|
||||||
@ -164,7 +209,7 @@ public static String extractData(Clob clob) throws Exception {
|
|||||||
|
|
||||||
public static String buildString(int size, char baseChar) {
|
public static String buildString(int size, char baseChar) {
|
||||||
StringBuilder buff = new StringBuilder();
|
StringBuilder buff = new StringBuilder();
|
||||||
for( int i = 0; i < size; i++ ) {
|
for ( int i = 0; i < size; i++ ) {
|
||||||
buff.append( baseChar );
|
buff.append( baseChar );
|
||||||
}
|
}
|
||||||
return buff.toString();
|
return buff.toString();
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.lob">
|
<hibernate-mapping package="org.hibernate.orm.test.lob">
|
||||||
|
|
||||||
<class name="LongByteArrayHolder" table="LOB_ENTITY_IMAGE">
|
<class name="LongByteArrayHolder" table="LOB_ENTITY_IMAGE">
|
||||||
<id name="id" type="long" column="ID">
|
<id name="id" type="long" column="ID">
|
@ -4,7 +4,9 @@
|
|||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests eager materialization and mutation of data mapped by
|
* Tests eager materialization and mutation of data mapped by
|
||||||
@ -12,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
xmlMappings = "org/hibernate/orm/test/lob/ImageMappings.hbm.xml"
|
||||||
|
)
|
||||||
public class ImageTest extends LongByteArrayTest {
|
public class ImageTest extends LongByteArrayTest {
|
||||||
public String[] getMappings() {
|
|
||||||
return new String[] { "lob/ImageMappings.hbm.xml" };
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* 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.orm.test.lob;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.Blob;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.hibernate.LobHelper;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.dialect.H2Dialect;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||||
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Setting;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Brett Meyer
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-7698")
|
||||||
|
@RequiresDialect(value = H2Dialect.class, comment = "HHH-7724")
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = LobEntity.class
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
@ServiceRegistry(
|
||||||
|
settings = @Setting(name = Environment.USE_STREAMS_FOR_BINARY, value = "true")
|
||||||
|
)
|
||||||
|
public class JpaLargeBlobTest {
|
||||||
|
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] { LobEntity.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void jpaBlobStream(SessionFactoryScope scope) throws Exception {
|
||||||
|
LobEntity o = new LobEntity();
|
||||||
|
LobInputStream inputStream = scope.fromSession(
|
||||||
|
session -> {
|
||||||
|
LobHelper lh = session.getLobHelper();
|
||||||
|
LobInputStream lis = new LobInputStream();
|
||||||
|
|
||||||
|
session.getTransaction().begin();
|
||||||
|
try {
|
||||||
|
Blob blob = lh.createBlob( lis, LobEntity.BLOB_LENGTH );
|
||||||
|
o.setBlob( blob );
|
||||||
|
|
||||||
|
// Regardless if NON_CONTEXTUAL_LOB_CREATION is set to true,
|
||||||
|
// ContextualLobCreator should use a NonContextualLobCreator to create
|
||||||
|
// a blob Proxy. If that's the case, the InputStream will not be read
|
||||||
|
// until it's persisted with the JDBC driver.
|
||||||
|
// Although HHH-7698 was about high memory consumption, this is the best
|
||||||
|
// way to test that the high memory use is being prevented.
|
||||||
|
assertFalse( lis.wasRead() );
|
||||||
|
|
||||||
|
session.persist( o );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
if ( session.getTransaction().isActive() ) {
|
||||||
|
session.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue( lis.wasRead() );
|
||||||
|
return lis;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LobInputStream extends InputStream {
|
||||||
|
private boolean read = false;
|
||||||
|
private Long count = (long) 200 * 1024 * 1024;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
read = true;
|
||||||
|
if ( count > 0 ) {
|
||||||
|
count--;
|
||||||
|
return new Random().nextInt();
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wasRead() {
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@
|
|||||||
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.lob">
|
<hibernate-mapping package="org.hibernate.orm.test.lob">
|
||||||
|
|
||||||
<class name="LobAsLastValueEntity">
|
<class name="LobAsLastValueEntity">
|
||||||
<id name="id" type="integer">
|
<id name="id" type="integer">
|
@ -4,7 +4,7 @@
|
|||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
@ -4,33 +4,32 @@
|
|||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import org.hibernate.testing.DialectChecks;
|
|
||||||
import org.hibernate.testing.RequiresDialectFeature;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Chris Cranford
|
* @author Chris Cranford
|
||||||
*/
|
*/
|
||||||
@RequiresDialectFeature(DialectChecks.ForceLobAsLastValue.class)
|
@RequiresDialectFeature(feature = DialectFeatureChecks.ForceLobAsLastValue.class)
|
||||||
@TestForIssue(jiraKey = "HHH-8382")
|
@TestForIssue(jiraKey = "HHH-8382")
|
||||||
public class LobAsLastValueTest extends BaseCoreFunctionalTestCase {
|
@DomainModel(
|
||||||
@Override
|
xmlMappings = "org/hibernate/orm/test/lob/LobAsLastValue.hbm.xml"
|
||||||
protected String[] getMappings() {
|
)
|
||||||
return new String[] { "lob/LobAsLastValue.hbm.xml" };
|
@SessionFactory
|
||||||
}
|
public class LobAsLastValueTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInsertLobAsLastValue() {
|
public void testInsertLobAsLastValue(SessionFactoryScope scope) {
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
scope.inTransaction( session -> {
|
||||||
byte[] details = new byte[4000];
|
byte[] details = new byte[4000];
|
||||||
byte[] title = new byte[2000];
|
byte[] title = new byte[2000];
|
||||||
|
|
||||||
@ -40,7 +39,11 @@ public void testInsertLobAsLastValue() {
|
|||||||
|
|
||||||
// This insert will fail on Oracle without the fix to ModelBinder flagging SimpleValue and Property as Lob
|
// This insert will fail on Oracle without the fix to ModelBinder flagging SimpleValue and Property as Lob
|
||||||
// because the fields will not be placed at the end of the insert, resulting in an Oracle failure.
|
// because the fields will not be placed at the end of the insert, resulting in an Oracle failure.
|
||||||
final LobAsLastValueEntity entity = new LobAsLastValueEntity( "Test", new String( details ), new String( title ) );
|
final LobAsLastValueEntity entity = new LobAsLastValueEntity(
|
||||||
|
"Test",
|
||||||
|
new String( details ),
|
||||||
|
new String( title )
|
||||||
|
);
|
||||||
session.save( entity );
|
session.save( entity );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
@ -4,7 +4,7 @@
|
|||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
import java.sql.Blob;
|
import java.sql.Blob;
|
||||||
|
|
@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* 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.orm.test.lob;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.sql.Clob;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.CockroachDialect;
|
||||||
|
import org.hibernate.dialect.PostgreSQLDialect;
|
||||||
|
import org.hibernate.query.Query;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||||
|
import org.hibernate.testing.orm.junit.RequiresDialects;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Lob;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-11477")
|
||||||
|
@RequiresDialects({ @RequiresDialect(PostgreSQLDialect.class), @RequiresDialect(CockroachDialect.class) })
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = LobStringTest.TestEntity.class
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class LobStringTest {
|
||||||
|
|
||||||
|
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' );
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
protected void prepareTest(SessionFactoryScope scope) throws Exception {
|
||||||
|
TestEntity entity = new TestEntity();
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
|
||||||
|
entity.setFirstLobField( value1 );
|
||||||
|
entity.setSecondLobField( value2 );
|
||||||
|
entity.setClobField( session.getLobHelper().createClob( value2 ) );
|
||||||
|
session.save( entity );
|
||||||
|
} );
|
||||||
|
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
final TestEntity testEntity = session.find( TestEntity.class, entity.getId() );
|
||||||
|
assertThat( testEntity.getFirstLobField(), is( value1 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.createQuery( "delete from TestEntity" ).executeUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-11477")
|
||||||
|
public void testHqlQuery(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( 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")
|
||||||
|
@RequiresDialect(PostgreSQLDialect.class)
|
||||||
|
public void testUsingStringLobAnnotatedPropertyInNativeQuery(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
final List<TestEntity> results = session.createNativeQuery(
|
||||||
|
"select te.* " +
|
||||||
|
"from test_entity te " +
|
||||||
|
"where lower(convert_from(lo_get(cast(te.firstLobField as oid)), 'UTF8')) LIKE :value",
|
||||||
|
TestEntity.class
|
||||||
|
)
|
||||||
|
.setParameter( "value", value1 )
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
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")
|
||||||
|
@RequiresDialect(PostgreSQLDialect.class)
|
||||||
|
public void testSelectStringLobAnnotatedInNativeQuery(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
final List<String> results = session.createNativeQuery(
|
||||||
|
"select convert_from(lo_get(cast(te.secondLobField as oid)), 'UTF8') " +
|
||||||
|
"from test_entity te " +
|
||||||
|
"where lower(convert_from(lo_get(cast(te.firstLobField as oid)), 'UTF8')) LIKE :value" )
|
||||||
|
.setParameter( "value", value1 )
|
||||||
|
.list();
|
||||||
|
|
||||||
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
|
||||||
|
assertThat( results.get( 0 ), is( value2 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-11477")
|
||||||
|
@RequiresDialect(PostgreSQLDialect.class)
|
||||||
|
public void testUsingLobPropertyInNativeQuery(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
final List<String> results = session.createNativeQuery(
|
||||||
|
"select convert_from(lo_get(cast(te.secondLobField as oid)), 'UTF8') " +
|
||||||
|
"from test_entity te " +
|
||||||
|
"where lower(convert_from(lo_get(cast(te.clobField as oid)), 'UTF8')) LIKE :value" )
|
||||||
|
.setParameter( "value", value2 )
|
||||||
|
.list();
|
||||||
|
|
||||||
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
|
||||||
|
assertThat( results.get( 0 ), is( value2 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-11477")
|
||||||
|
@RequiresDialect(PostgreSQLDialect.class)
|
||||||
|
public void testSelectClobPropertyInNativeQuery(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
final List<byte[]> results = session.createNativeQuery(
|
||||||
|
"select lo_get(cast(te.clobField as oid)) " +
|
||||||
|
"from test_entity te " +
|
||||||
|
"where lower(convert_from(lo_get(cast(te.clobField as oid)), 'UTF8')) LIKE :value" )
|
||||||
|
.setParameter( "value", value2 )
|
||||||
|
.list();
|
||||||
|
|
||||||
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
|
||||||
|
try {
|
||||||
|
assertThat( new String( results.get( 0 ), "UTF8" ), is( value2 ) );
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String buildRecursively(int size, char baseChar) {
|
||||||
|
StringBuilder buff = new StringBuilder();
|
||||||
|
for ( int i = 0; i < size; i++ ) {
|
||||||
|
buff.append( baseChar );
|
||||||
|
}
|
||||||
|
return buff.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
//$Id: $
|
//$Id: $
|
||||||
|
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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.orm.test.lob;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.SybaseASEDialect;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests eager materialization and mutation of long byte arrays.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@SessionFactory
|
||||||
|
public abstract class LongByteArrayTest {
|
||||||
|
private static final int ARRAY_SIZE = 10000;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBoundedLongByteArrayAccess(SessionFactoryScope scope) {
|
||||||
|
byte[] original = buildRecursively( ARRAY_SIZE, true );
|
||||||
|
byte[] changed = buildRecursively( ARRAY_SIZE, false );
|
||||||
|
byte[] empty = new byte[] {};
|
||||||
|
|
||||||
|
Long id = scope.fromTransaction(
|
||||||
|
session -> {
|
||||||
|
LongByteArrayHolder entity = new LongByteArrayHolder();
|
||||||
|
session.save( entity );
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongByteArrayHolder entity = session.get( LongByteArrayHolder.class, id );
|
||||||
|
assertNull( entity.getLongByteArray() );
|
||||||
|
entity.setLongByteArray( original );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongByteArrayHolder entity = session.get( LongByteArrayHolder.class, id );
|
||||||
|
Assertions.assertEquals( ARRAY_SIZE, entity.getLongByteArray().length );
|
||||||
|
assertEquals( original, entity.getLongByteArray() );
|
||||||
|
entity.setLongByteArray( changed );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongByteArrayHolder entity = session.get( LongByteArrayHolder.class, id );
|
||||||
|
Assertions.assertEquals( ARRAY_SIZE, entity.getLongByteArray().length );
|
||||||
|
assertEquals( changed, entity.getLongByteArray() );
|
||||||
|
entity.setLongByteArray( null );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongByteArrayHolder entity = session.get( LongByteArrayHolder.class, id );
|
||||||
|
assertNull( entity.getLongByteArray() );
|
||||||
|
entity.setLongByteArray( empty );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase returns byte[]{0}")
|
||||||
|
public void testEmptyArray(SessionFactoryScope scope) {
|
||||||
|
byte[] empty = new byte[] {};
|
||||||
|
|
||||||
|
LongByteArrayHolder longByteArrayHolder = new LongByteArrayHolder();
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
longByteArrayHolder.setLongByteArray( empty );
|
||||||
|
session.save( longByteArrayHolder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongByteArrayHolder entity = session.get( LongByteArrayHolder.class, longByteArrayHolder.getId() );
|
||||||
|
if ( entity.getLongByteArray() != null ) {
|
||||||
|
Assertions.assertEquals( empty.length, entity.getLongByteArray().length );
|
||||||
|
assertEquals( empty, entity.getLongByteArray() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSaving(SessionFactoryScope scope) {
|
||||||
|
byte[] value = buildRecursively( ARRAY_SIZE, true );
|
||||||
|
|
||||||
|
Long id = scope.fromTransaction(
|
||||||
|
session -> {
|
||||||
|
LongByteArrayHolder entity = new LongByteArrayHolder();
|
||||||
|
entity.setLongByteArray( value );
|
||||||
|
session.persist( entity );
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongByteArrayHolder entity = session.get( LongByteArrayHolder.class, id );
|
||||||
|
Assertions.assertEquals( ARRAY_SIZE, entity.getLongByteArray().length );
|
||||||
|
assertEquals( value, entity.getLongByteArray() );
|
||||||
|
session.delete( entity );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.createQuery( "delete from LongByteArrayHolder" ).executeUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] buildRecursively(int size, boolean on) {
|
||||||
|
byte[] data = new byte[size];
|
||||||
|
data[0] = mask( on );
|
||||||
|
for ( int i = 0; i < size; i++ ) {
|
||||||
|
data[i] = mask( on );
|
||||||
|
on = !on;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte mask(boolean on) {
|
||||||
|
return on ? (byte) 1 : (byte) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertEquals(byte[] val1, byte[] val2) {
|
||||||
|
if ( !Arrays.equals( val1, val2 ) ) {
|
||||||
|
fail( "byte arrays did not match" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
//$Id: $
|
//$Id: $
|
||||||
|
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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.orm.test.lob;
|
||||||
|
|
||||||
|
|
||||||
|
import org.hibernate.dialect.SybaseASEDialect;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests eager materialization and mutation of long strings.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "UnusedDeclaration" })
|
||||||
|
@SessionFactory
|
||||||
|
public abstract class LongStringTest {
|
||||||
|
private static final int LONG_STRING_SIZE = 10000;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBoundedLongStringAccess(SessionFactoryScope scope) {
|
||||||
|
String original = buildRecursively( LONG_STRING_SIZE, 'x' );
|
||||||
|
String changed = buildRecursively( LONG_STRING_SIZE, 'y' );
|
||||||
|
String empty = "";
|
||||||
|
|
||||||
|
Long id = scope.fromTransaction(
|
||||||
|
session -> {
|
||||||
|
LongStringHolder entity = new LongStringHolder();
|
||||||
|
session.save( entity );
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongStringHolder entity = session.get( LongStringHolder.class, id );
|
||||||
|
assertNull( entity.getLongString() );
|
||||||
|
entity.setLongString( original );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongStringHolder entity = session.get( LongStringHolder.class, id );
|
||||||
|
assertEquals( LONG_STRING_SIZE, entity.getLongString().length() );
|
||||||
|
assertEquals( original, entity.getLongString() );
|
||||||
|
entity.setLongString( changed );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongStringHolder entity = session.get( LongStringHolder.class, id );
|
||||||
|
assertEquals( LONG_STRING_SIZE, entity.getLongString().length() );
|
||||||
|
assertEquals( changed, entity.getLongString() );
|
||||||
|
entity.setLongString( null );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongStringHolder entity = session.get( LongStringHolder.class, id );
|
||||||
|
assertNull( entity.getLongString() );
|
||||||
|
entity.setLongString( empty );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
LongStringHolder entity = session.get( LongStringHolder.class, id );
|
||||||
|
if ( entity.getLongString() != null ) {
|
||||||
|
if ( scope.getSessionFactory().getJdbcServices().getDialect() instanceof SybaseASEDialect ) {
|
||||||
|
//Sybase uses a single blank to denote an empty string (this is by design). So, when inserting an empty string '', it is interpreted as single blank ' '.
|
||||||
|
assertEquals( empty.length(), entity.getLongString().trim().length() );
|
||||||
|
assertEquals( empty, entity.getLongString().trim() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertEquals( empty.length(), entity.getLongString().length() );
|
||||||
|
assertEquals( empty, entity.getLongString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session.delete( entity );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildRecursively(int size, char baseChar) {
|
||||||
|
StringBuilder buff = new StringBuilder();
|
||||||
|
for ( int i = 0; i < size; i++ ) {
|
||||||
|
buff.append( baseChar );
|
||||||
|
}
|
||||||
|
return buff.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@
|
|||||||
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.lob">
|
<hibernate-mapping package="org.hibernate.orm.test.lob">
|
||||||
|
|
||||||
<class name="LongByteArrayHolder" table="LOB_ENTITY_MAT_BLOB">
|
<class name="LongByteArrayHolder" table="LOB_ENTITY_MAT_BLOB">
|
||||||
<id name="id" type="long" column="ID">
|
<id name="id" type="long" column="ID">
|
@ -4,10 +4,12 @@
|
|||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
import org.hibernate.testing.DialectChecks;
|
|
||||||
import org.hibernate.testing.RequiresDialectFeature;
|
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests eager materialization and mutation of data mapped by
|
* Tests eager materialization and mutation of data mapped by
|
||||||
@ -16,11 +18,11 @@
|
|||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
@RequiresDialectFeature(
|
@RequiresDialectFeature(
|
||||||
value = DialectChecks.SupportsExpectedLobUsagePattern.class,
|
feature = DialectFeatureChecks.SupportsExpectedLobUsagePattern.class,
|
||||||
comment = "database/driver does not support expected LOB usage pattern"
|
comment = "database/driver does not support expected LOB usage pattern"
|
||||||
)
|
)
|
||||||
|
@DomainModel(
|
||||||
|
xmlMappings = "org/hibernate/orm/test/lob/MaterializedBlobMappings.hbm.xml"
|
||||||
|
)
|
||||||
public class MaterializedBlobTest extends LongByteArrayTest {
|
public class MaterializedBlobTest extends LongByteArrayTest {
|
||||||
public String[] getMappings() {
|
|
||||||
return new String[] { "lob/MaterializedBlobMappings.hbm.xml" };
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -9,7 +9,7 @@
|
|||||||
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.lob">
|
<hibernate-mapping package="org.hibernate.orm.test.lob">
|
||||||
|
|
||||||
<class name="LongStringHolder" table="LOB_ENTITY_MAT_CLOB">
|
<class name="LongStringHolder" table="LOB_ENTITY_MAT_CLOB">
|
||||||
<id name="id" type="long" column="ID">
|
<id name="id" type="long" column="ID">
|
@ -4,10 +4,11 @@
|
|||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
import org.hibernate.testing.DialectChecks;
|
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||||
import org.hibernate.testing.RequiresDialectFeature;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests eager materialization and mutation of data mapped by
|
* Tests eager materialization and mutation of data mapped by
|
||||||
@ -15,9 +16,9 @@
|
|||||||
*
|
*
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
@RequiresDialectFeature( DialectChecks.SupportsExpectedLobUsagePattern.class )
|
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsExpectedLobUsagePattern.class)
|
||||||
|
@DomainModel(
|
||||||
|
xmlMappings = "org/hibernate/orm/test/lob/MaterializedClobMappings.hbm.xml"
|
||||||
|
)
|
||||||
public class MaterializedClobTest extends LongStringTest {
|
public class MaterializedClobTest extends LongStringTest {
|
||||||
public String[] getMappings() {
|
|
||||||
return new String[] { "lob/MaterializedClobMappings.hbm.xml" };
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* 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.orm.test.lob;
|
||||||
|
|
||||||
|
import java.sql.Clob;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.PostgreSQLDialect;
|
||||||
|
import org.hibernate.query.Query;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.hibernate.testing.util.ExceptionUtil;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Lob;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-11614")
|
||||||
|
@RequiresDialect(PostgreSQLDialect.class)
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = PostgreSqlLobStringTest.TestEntity.class
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class PostgreSqlLobStringTest {
|
||||||
|
|
||||||
|
private final String value1 = "abc";
|
||||||
|
private final String value2 = "def";
|
||||||
|
private final String value3 = "ghi";
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
protected void prepareTest(SessionFactoryScope scope)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.doWork( connection -> {
|
||||||
|
try (PreparedStatement statement = connection.prepareStatement(
|
||||||
|
"insert \n" +
|
||||||
|
" into\n" +
|
||||||
|
" TEST_ENTITY\n" +
|
||||||
|
" (firstLobField, secondLobField, clobfield, id) \n" +
|
||||||
|
" values\n" +
|
||||||
|
" (?, ?, ?, -1)"
|
||||||
|
)) {
|
||||||
|
int index = 1;
|
||||||
|
statement.setString( index++, value1 );
|
||||||
|
statement.setString( index++, value2 );
|
||||||
|
statement.setString( index++, value3 );
|
||||||
|
|
||||||
|
assertEquals( 1, statement.executeUpdate() );
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBadClobDataSavedAsStringFails(SessionFactoryScope scope) {
|
||||||
|
try {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final Query query = session.createQuery( "from TestEntity" );
|
||||||
|
|
||||||
|
final List<TestEntity> results = query.list();
|
||||||
|
|
||||||
|
fail( "Exception thrown expected" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Exception rootException = (Exception) ExceptionUtil.rootCause( e );
|
||||||
|
assertTrue( rootException.getMessage().startsWith( "Bad value for type long" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBadClobDataSavedAsStringworksAfterUpdate(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
|
||||||
|
session.doWork( connection -> {
|
||||||
|
try (Statement statement = connection.createStatement()) {
|
||||||
|
statement.executeUpdate(
|
||||||
|
"update test_entity\n" +
|
||||||
|
"set \n" +
|
||||||
|
" clobfield = lo_from_bytea(0, cast(clobfield as bytea)),\n" +
|
||||||
|
" firstlobfield = lo_from_bytea(0, cast(firstlobfield as bytea)),\n" +
|
||||||
|
" secondlobfield = lo_from_bytea(0, cast(secondlobfield as bytea))"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
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( value3 ) );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
fail( e.getMessage() );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void cleanUp(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session ->
|
||||||
|
session.createQuery( "delete from TestEntity" ).executeUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "TestEntity")
|
||||||
|
@Table(name = "TEST_ENTITY")
|
||||||
|
public static class TestEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Lob
|
||||||
|
@Column
|
||||||
|
String firstLobField;
|
||||||
|
|
||||||
|
@Lob
|
||||||
|
@Column
|
||||||
|
String secondLobField;
|
||||||
|
|
||||||
|
@Lob
|
||||||
|
@Column
|
||||||
|
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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// protected boolean isCleanupTestDataUsingBulkDelete() {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
}
|
@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// $Id: SerializableData.java 4704 2004-11-04 21:59:22Z steveebersole $
|
// $Id: SerializableData.java 4704 2004-11-04 21:59:22Z steveebersole $
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
//$Id: $
|
//$Id: $
|
||||||
|
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
@ -9,7 +9,7 @@
|
|||||||
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.lob">
|
<hibernate-mapping package="org.hibernate.orm.test.lob">
|
||||||
|
|
||||||
<!-- HHH-7734: Don't use LOB_ENTITY as the table name. Others use it
|
<!-- HHH-7734: Don't use LOB_ENTITY as the table name. Others use it
|
||||||
and there were some odd locking issue with 1 version of Oracle. -->
|
and there were some odd locking issue with 1 version of Oracle. -->
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* 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.orm.test.lob;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.SybaseASEDialect;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests of {@link org.hibernate.type.SerializableType}
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
xmlMappings = "org/hibernate/orm/test/lob/SerializableMappings.hbm.xml"
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class SerializableTypeTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SkipForDialect(dialectClass = SybaseASEDialect.class, version = 1500, matchSubTypes = true, reason = "HHH-6425")
|
||||||
|
public void testNewSerializableType(SessionFactoryScope scope) {
|
||||||
|
final String initialPayloadText = "Initial payload";
|
||||||
|
final String changedPayloadText = "Changed payload";
|
||||||
|
final String empty = "";
|
||||||
|
|
||||||
|
SerializableHolder serializableHolder = scope.fromTransaction(
|
||||||
|
session -> {
|
||||||
|
SerializableHolder holder = new SerializableHolder();
|
||||||
|
session.save( holder );
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Long id = serializableHolder.getId();
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
SerializableHolder holder = session.get( SerializableHolder.class, id );
|
||||||
|
assertNull( holder.getSerialData() );
|
||||||
|
holder.setSerialData( new SerializableData( initialPayloadText ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
SerializableHolder holder = session.get( SerializableHolder.class, id );
|
||||||
|
SerializableData serialData = (SerializableData) holder.getSerialData();
|
||||||
|
assertEquals( initialPayloadText, serialData.getPayload() );
|
||||||
|
holder.setSerialData( new SerializableData( changedPayloadText ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
SerializableHolder holder = session.get( SerializableHolder.class, id );
|
||||||
|
SerializableData serialData = (SerializableData) holder.getSerialData();
|
||||||
|
assertEquals( changedPayloadText, serialData.getPayload() );
|
||||||
|
holder.setSerialData( null );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
SerializableHolder holder = session.get( SerializableHolder.class, id );
|
||||||
|
assertNull( holder.getSerialData() );
|
||||||
|
holder.setSerialData( new SerializableData( empty ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
SerializableHolder holder = session.get( SerializableHolder.class, id );
|
||||||
|
SerializableData serialData = (SerializableData) holder.getSerialData();
|
||||||
|
assertEquals( empty, serialData.getPayload() );
|
||||||
|
session.delete( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,7 +9,7 @@
|
|||||||
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
|
||||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
<hibernate-mapping package="org.hibernate.test.lob">
|
<hibernate-mapping package="org.hibernate.orm.test.lob">
|
||||||
|
|
||||||
<class name="LongStringHolder" table="LOB_ENTITY_TEXT">
|
<class name="LongStringHolder" table="LOB_ENTITY_TEXT">
|
||||||
<id name="id" type="long" column="ID">
|
<id name="id" type="long" column="ID">
|
@ -4,7 +4,9 @@
|
|||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.lob;
|
package org.hibernate.orm.test.lob;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test eager materialization and mutation data mapped by
|
* Test eager materialization and mutation data mapped by
|
||||||
@ -12,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
xmlMappings = "org/hibernate/orm/test/lob/TextMappings.hbm.xml"
|
||||||
|
)
|
||||||
public class TextTest extends LongStringTest {
|
public class TextTest extends LongStringTest {
|
||||||
public String[] getMappings() {
|
|
||||||
return new String[] { "lob/TextMappings.hbm.xml" };
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.sql.Blob;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import org.hibernate.LobHelper;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.dialect.H2Dialect;
|
|
||||||
import org.hibernate.testing.RequiresDialect;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Brett Meyer
|
|
||||||
*/
|
|
||||||
@TestForIssue( jiraKey = "HHH-7698" )
|
|
||||||
@RequiresDialect( value = H2Dialect.class, jiraKey = "HHH-7724" )
|
|
||||||
public class JpaLargeBlobTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class<?>[] { LobEntity.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.setProperty(Environment.USE_STREAMS_FOR_BINARY, "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void jpaBlobStream() throws Exception {
|
|
||||||
Session session = openSession();
|
|
||||||
LobEntity o = new LobEntity();
|
|
||||||
|
|
||||||
LobHelper lh = session.getLobHelper();
|
|
||||||
LobInputStream lis = new LobInputStream();
|
|
||||||
|
|
||||||
session.getTransaction().begin();
|
|
||||||
|
|
||||||
Blob blob = lh.createBlob(lis, LobEntity.BLOB_LENGTH);
|
|
||||||
o.setBlob(blob);
|
|
||||||
|
|
||||||
// Regardless if NON_CONTEXTUAL_LOB_CREATION is set to true,
|
|
||||||
// ContextualLobCreator should use a NonContextualLobCreator to create
|
|
||||||
// a blob Proxy. If that's the case, the InputStream will not be read
|
|
||||||
// until it's persisted with the JDBC driver.
|
|
||||||
// Although HHH-7698 was about high memory consumption, this is the best
|
|
||||||
// way to test that the high memory use is being prevented.
|
|
||||||
assertFalse( lis.wasRead() );
|
|
||||||
|
|
||||||
session.persist(o);
|
|
||||||
session.getTransaction().commit();
|
|
||||||
|
|
||||||
assertTrue( lis.wasRead() );
|
|
||||||
|
|
||||||
session.close();
|
|
||||||
|
|
||||||
lis.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LobInputStream extends InputStream {
|
|
||||||
private boolean read = false;
|
|
||||||
private Long count = (long) 200 * 1024 * 1024;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
read = true;
|
|
||||||
if (count > 0) {
|
|
||||||
count--;
|
|
||||||
return new Random().nextInt();
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int available() throws IOException {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean wasRead() {
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,237 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.io.UnsupportedEncodingException;
|
|
||||||
import java.sql.Clob;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.List;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.Lob;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
|
|
||||||
import org.hibernate.dialect.CockroachDialect;
|
|
||||||
import org.hibernate.dialect.PostgreSQLDialect;
|
|
||||||
import org.hibernate.query.Query;
|
|
||||||
import org.hibernate.testing.RequiresDialect;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hamcrest.core.Is.is;
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Andrea Boriero
|
|
||||||
*/
|
|
||||||
@TestForIssue(jiraKey = "HHH-11477")
|
|
||||||
@RequiresDialect({ PostgreSQLDialect.class, CockroachDialect.class })
|
|
||||||
public class LobStringTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
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();
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
|
||||||
|
|
||||||
entity.setFirstLobField( value1 );
|
|
||||||
entity.setSecondLobField( value2 );
|
|
||||||
entity.setClobField( session.getLobHelper().createClob( value2 ) );
|
|
||||||
session.save( entity );
|
|
||||||
} );
|
|
||||||
|
|
||||||
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() {
|
|
||||||
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")
|
|
||||||
@RequiresDialect(PostgreSQLDialect.class)
|
|
||||||
public void testUsingStringLobAnnotatedPropertyInNativeQuery() {
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
|
||||||
final List<TestEntity> results = session.createNativeQuery(
|
|
||||||
"select te.* " +
|
|
||||||
"from test_entity te " +
|
|
||||||
"where lower(convert_from(lo_get(cast(te.firstLobField as oid)), 'UTF8')) LIKE :value", TestEntity.class )
|
|
||||||
.setParameter( "value", value1 )
|
|
||||||
.getResultList();
|
|
||||||
|
|
||||||
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")
|
|
||||||
@RequiresDialect(PostgreSQLDialect.class)
|
|
||||||
public void testSelectStringLobAnnotatedInNativeQuery() {
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
|
||||||
final List<String> results = session.createNativeQuery(
|
|
||||||
"select convert_from(lo_get(cast(te.secondLobField as oid)), 'UTF8') " +
|
|
||||||
"from test_entity te " +
|
|
||||||
"where lower(convert_from(lo_get(cast(te.firstLobField as oid)), 'UTF8')) LIKE :value" )
|
|
||||||
.setParameter( "value", value1 )
|
|
||||||
.list();
|
|
||||||
|
|
||||||
assertThat( results.size(), is( 1 ) );
|
|
||||||
|
|
||||||
assertThat( results.get( 0 ), is( value2 ) );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue(jiraKey = "HHH-11477")
|
|
||||||
@RequiresDialect(PostgreSQLDialect.class)
|
|
||||||
public void testUsingLobPropertyInNativeQuery() {
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
|
||||||
final List<String> results = session.createNativeQuery(
|
|
||||||
"select convert_from(lo_get(cast(te.secondLobField as oid)), 'UTF8') " +
|
|
||||||
"from test_entity te " +
|
|
||||||
"where lower(convert_from(lo_get(cast(te.clobField as oid)), 'UTF8')) LIKE :value" )
|
|
||||||
.setParameter( "value", value2 )
|
|
||||||
.list();
|
|
||||||
|
|
||||||
assertThat( results.size(), is( 1 ) );
|
|
||||||
|
|
||||||
assertThat( results.get( 0 ), is( value2 ) );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue(jiraKey = "HHH-11477")
|
|
||||||
@RequiresDialect(PostgreSQLDialect.class)
|
|
||||||
public void testSelectClobPropertyInNativeQuery() {
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
|
||||||
final List<byte[]> results = session.createNativeQuery(
|
|
||||||
"select lo_get(cast(te.clobField as oid)) " +
|
|
||||||
"from test_entity te " +
|
|
||||||
"where lower(convert_from(lo_get(cast(te.clobField as oid)), 'UTF8')) LIKE :value" )
|
|
||||||
.setParameter( "value", value2 )
|
|
||||||
.list();
|
|
||||||
|
|
||||||
assertThat( results.size(), is( 1 ) );
|
|
||||||
|
|
||||||
try {
|
|
||||||
assertThat( new String( results.get( 0 ), "UTF8"), is( value2 ) );
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException 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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.util.Arrays;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import junit.framework.AssertionFailedError;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests eager materialization and mutation of long byte arrays.
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public abstract class LongByteArrayTest extends BaseCoreFunctionalTestCase {
|
|
||||||
private static final int ARRAY_SIZE = 10000;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBoundedLongByteArrayAccess() {
|
|
||||||
byte[] original = buildRecursively( ARRAY_SIZE, true );
|
|
||||||
byte[] changed = buildRecursively( ARRAY_SIZE, false );
|
|
||||||
byte[] empty = new byte[] {};
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
LongByteArrayHolder entity = new LongByteArrayHolder();
|
|
||||||
s.save( entity );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = s.get( LongByteArrayHolder.class, entity.getId() );
|
|
||||||
assertNull( entity.getLongByteArray() );
|
|
||||||
entity.setLongByteArray( original );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = s.get( LongByteArrayHolder.class, entity.getId() );
|
|
||||||
Assert.assertEquals( ARRAY_SIZE, entity.getLongByteArray().length );
|
|
||||||
assertEquals( original, entity.getLongByteArray() );
|
|
||||||
entity.setLongByteArray( changed );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = s.get( LongByteArrayHolder.class, entity.getId() );
|
|
||||||
Assert.assertEquals( ARRAY_SIZE, entity.getLongByteArray().length );
|
|
||||||
assertEquals( changed, entity.getLongByteArray() );
|
|
||||||
entity.setLongByteArray( null );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = s.get( LongByteArrayHolder.class, entity.getId() );
|
|
||||||
assertNull( entity.getLongByteArray() );
|
|
||||||
entity.setLongByteArray( empty );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = s.get( LongByteArrayHolder.class, entity.getId() );
|
|
||||||
if ( entity.getLongByteArray() != null ) {
|
|
||||||
Assert.assertEquals( empty.length, entity.getLongByteArray().length );
|
|
||||||
assertEquals( empty, entity.getLongByteArray() );
|
|
||||||
}
|
|
||||||
s.delete( entity );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSaving() {
|
|
||||||
byte[] value = buildRecursively( ARRAY_SIZE, true );
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
LongByteArrayHolder entity = new LongByteArrayHolder();
|
|
||||||
entity.setLongByteArray( value );
|
|
||||||
s.persist( entity );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = ( LongByteArrayHolder ) s.get( LongByteArrayHolder.class, entity.getId() );
|
|
||||||
Assert.assertEquals( ARRAY_SIZE, entity.getLongByteArray().length );
|
|
||||||
assertEquals( value, entity.getLongByteArray() );
|
|
||||||
s.delete( entity );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] buildRecursively(int size, boolean on) {
|
|
||||||
byte[] data = new byte[size];
|
|
||||||
data[0] = mask( on );
|
|
||||||
for ( int i = 0; i < size; i++ ) {
|
|
||||||
data[i] = mask( on );
|
|
||||||
on = !on;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte mask(boolean on) {
|
|
||||||
return on ? ( byte ) 1 : ( byte ) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void assertEquals(byte[] val1, byte[] val2) {
|
|
||||||
if ( !Arrays.equals( val1, val2 ) ) {
|
|
||||||
throw new AssertionFailedError( "byte arrays did not match" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 org.junit.Test;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.dialect.SybaseASE15Dialect;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests eager materialization and mutation of long strings.
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
@SuppressWarnings( {"UnusedDeclaration"})
|
|
||||||
public abstract class LongStringTest extends BaseCoreFunctionalTestCase {
|
|
||||||
private static final int LONG_STRING_SIZE = 10000;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBoundedLongStringAccess() {
|
|
||||||
String original = buildRecursively( LONG_STRING_SIZE, 'x' );
|
|
||||||
String changed = buildRecursively( LONG_STRING_SIZE, 'y' );
|
|
||||||
String empty = "";
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
LongStringHolder entity = new LongStringHolder();
|
|
||||||
s.save( entity );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() );
|
|
||||||
assertNull( entity.getLongString() );
|
|
||||||
entity.setLongString( original );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() );
|
|
||||||
assertEquals( LONG_STRING_SIZE, entity.getLongString().length() );
|
|
||||||
assertEquals( original, entity.getLongString() );
|
|
||||||
entity.setLongString( changed );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() );
|
|
||||||
assertEquals( LONG_STRING_SIZE, entity.getLongString().length() );
|
|
||||||
assertEquals( changed, entity.getLongString() );
|
|
||||||
entity.setLongString( null );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() );
|
|
||||||
assertNull( entity.getLongString() );
|
|
||||||
entity.setLongString( empty );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() );
|
|
||||||
if ( entity.getLongString() != null ) {
|
|
||||||
if(getDialect() instanceof SybaseASE15Dialect){
|
|
||||||
//Sybase uses a single blank to denote an empty string (this is by design). So, when inserting an empty string '', it is interpreted as single blank ' '.
|
|
||||||
assertEquals( empty.length(), entity.getLongString().trim().length() );
|
|
||||||
assertEquals( empty, entity.getLongString().trim() );
|
|
||||||
}else{
|
|
||||||
assertEquals( empty.length(), entity.getLongString().length() );
|
|
||||||
assertEquals( empty, entity.getLongString() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.delete( entity );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildRecursively(int size, char baseChar) {
|
|
||||||
StringBuilder buff = new StringBuilder();
|
|
||||||
for( int i = 0; i < size; i++ ) {
|
|
||||||
buff.append( baseChar );
|
|
||||||
}
|
|
||||||
return buff.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.PreparedStatement;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.List;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.Lob;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
|
|
||||||
import org.hibernate.dialect.PostgreSQLDialect;
|
|
||||||
import org.hibernate.query.Query;
|
|
||||||
|
|
||||||
import org.hibernate.testing.*;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.hibernate.testing.util.ExceptionUtil;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hamcrest.core.Is.is;
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Andrea Boriero
|
|
||||||
*/
|
|
||||||
@TestForIssue(jiraKey = "HHH-11614")
|
|
||||||
@RequiresDialect(PostgreSQLDialect.class)
|
|
||||||
public class PostgreSqlLobStringTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
private final String value1 = "abc";
|
|
||||||
private final String value2 = "def";
|
|
||||||
private final String value3 = "ghi";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] {TestEntity.class};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void prepareTest()
|
|
||||||
throws Exception {
|
|
||||||
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
|
||||||
|
|
||||||
session.doWork( connection -> {
|
|
||||||
try(PreparedStatement statement = connection.prepareStatement(
|
|
||||||
"insert \n" +
|
|
||||||
" into\n" +
|
|
||||||
" TEST_ENTITY\n" +
|
|
||||||
" (firstLobField, secondLobField, clobfield, id) \n" +
|
|
||||||
" values\n" +
|
|
||||||
" (?, ?, ?, -1)"
|
|
||||||
)) {
|
|
||||||
int index = 1;
|
|
||||||
statement.setString(index++, value1);
|
|
||||||
statement.setString(index++, value2);
|
|
||||||
statement.setString(index++, value3);
|
|
||||||
|
|
||||||
assertEquals( 1, statement.executeUpdate() );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBadClobDataSavedAsStringFails() {
|
|
||||||
try {
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
|
||||||
final Query query = session.createQuery( "from TestEntity" );
|
|
||||||
|
|
||||||
final List<TestEntity> results = query.list();
|
|
||||||
|
|
||||||
fail("Exception thrown expected");
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
Exception rootException = (Exception) ExceptionUtil.rootCause( e );
|
|
||||||
assertTrue( rootException.getMessage().startsWith( "Bad value for type long" ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBadClobDataSavedAsStringworksAfterUpdate() {
|
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
|
||||||
|
|
||||||
session.doWork( connection -> {
|
|
||||||
try(Statement statement = connection.createStatement()) {
|
|
||||||
statement.executeUpdate(
|
|
||||||
"update test_entity\n" +
|
|
||||||
"set \n" +
|
|
||||||
" clobfield = lo_from_bytea(0, cast(clobfield as bytea)),\n" +
|
|
||||||
" firstlobfield = lo_from_bytea(0, cast(firstlobfield as bytea)),\n" +
|
|
||||||
" secondlobfield = lo_from_bytea(0, cast(secondlobfield as bytea))"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
} );
|
|
||||||
|
|
||||||
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( value3 ) );
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
fail( e.getMessage() );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "TestEntity")
|
|
||||||
@Table(name = "TEST_ENTITY")
|
|
||||||
public static class TestEntity {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private long id;
|
|
||||||
|
|
||||||
@Lob
|
|
||||||
@Column
|
|
||||||
String firstLobField;
|
|
||||||
|
|
||||||
@Lob
|
|
||||||
@Column
|
|
||||||
String secondLobField;
|
|
||||||
|
|
||||||
@Lob
|
|
||||||
@Column
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isCleanupTestDataUsingBulkDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 org.junit.Test;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.dialect.SybaseASE15Dialect;
|
|
||||||
import org.hibernate.testing.SkipForDialect;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests of {@link org.hibernate.type.SerializableType}
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class SerializableTypeTest extends BaseCoreFunctionalTestCase {
|
|
||||||
public String[] getMappings() {
|
|
||||||
return new String[] { "lob/SerializableMappings.hbm.xml" };
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCacheConcurrencyStrategy() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SkipForDialect( value = SybaseASE15Dialect.class, jiraKey = "HHH-6425")
|
|
||||||
public void testNewSerializableType() {
|
|
||||||
final String initialPayloadText = "Initial payload";
|
|
||||||
final String changedPayloadText = "Changed payload";
|
|
||||||
final String empty = "";
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
SerializableHolder holder = new SerializableHolder();
|
|
||||||
s.save( holder );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() );
|
|
||||||
assertNull( holder.getSerialData() );
|
|
||||||
holder.setSerialData( new SerializableData( initialPayloadText ) );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() );
|
|
||||||
SerializableData serialData = ( SerializableData ) holder.getSerialData();
|
|
||||||
assertEquals( initialPayloadText, serialData.getPayload() );
|
|
||||||
holder.setSerialData( new SerializableData( changedPayloadText ) );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() );
|
|
||||||
serialData = ( SerializableData ) holder.getSerialData();
|
|
||||||
assertEquals( changedPayloadText, serialData.getPayload() );
|
|
||||||
holder.setSerialData( null );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() );
|
|
||||||
assertNull( holder.getSerialData() );
|
|
||||||
holder.setSerialData( new SerializableData( empty ) );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
|
||||||
s.beginTransaction();
|
|
||||||
holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() );
|
|
||||||
serialData = ( SerializableData ) holder.getSerialData();
|
|
||||||
assertEquals( empty, serialData.getPayload() );
|
|
||||||
s.delete( holder );
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -368,4 +368,10 @@ public boolean apply(Dialect dialect) {
|
|||||||
return dialect.currentTimestamp().startsWith( "current_timestamp" );
|
return dialect.currentTimestamp().startsWith( "current_timestamp" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ForceLobAsLastValue implements DialectFeatureCheck {
|
||||||
|
public boolean apply(Dialect dialect) {
|
||||||
|
return dialect.forceLobAsLastValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user