HHH-14408 Test that user type provided by integrator is properly registered
This commit is contained in:
parent
d213d675ce
commit
6fcb83c90d
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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.usertype;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.internal.util.ConfigHelper;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class IntegratorProvidedUserTypeTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
StringWrapperTestEntity.class
|
||||
};
|
||||
}
|
||||
|
||||
protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) {
|
||||
builder.applyClassLoader( new TestClassLoader() );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-14408" )
|
||||
public void test() {
|
||||
Type type = sessionFactory().getMetamodel().entityPersister( StringWrapperTestEntity.class )
|
||||
.getPropertyType( "stringWrapper" );
|
||||
Assert.assertTrue( "Type was initialized too early i.e. before integrators were run", type instanceof CustomType );
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class StringWrapperTestEntity implements Serializable {
|
||||
@Id
|
||||
private Integer id;
|
||||
private StringWrapper stringWrapper;
|
||||
}
|
||||
|
||||
private static class TestClassLoader extends ClassLoader {
|
||||
|
||||
/**
|
||||
* testStoppableClassLoaderService() needs a custom JDK service implementation. Rather than using a real one
|
||||
* on the test classpath, force it in here.
|
||||
*/
|
||||
@Override
|
||||
protected Enumeration<URL> findResources(String name) throws IOException {
|
||||
if (name.equals( "META-INF/services/org.hibernate.integrator.spi.Integrator" )) {
|
||||
final URL serviceUrl = ConfigHelper.findAsResource(
|
||||
"org/hibernate/test/service/org.hibernate.integrator.spi.Integrator" );
|
||||
return new Enumeration<URL>() {
|
||||
boolean hasMore = true;
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements() {
|
||||
return hasMore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL nextElement() {
|
||||
hasMore = false;
|
||||
return serviceUrl;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return java.util.Collections.enumeration( java.util.Collections.<URL>emptyList() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloading class from binary file.
|
||||
*
|
||||
* @param originalClass Original class.
|
||||
* @throws IOException .
|
||||
*/
|
||||
public void overrideClass(final Class<?> originalClass) throws IOException {
|
||||
String originalPath = "/" + originalClass.getName().replaceAll("\\.", "/") + ".class";
|
||||
InputStream inputStream = originalClass.getResourceAsStream( originalPath);
|
||||
Assert.assertNotNull(inputStream);
|
||||
try {
|
||||
byte[] data = toByteArray( inputStream );
|
||||
defineClass(originalClass.getName(), data, 0, data.length);
|
||||
} finally {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] toByteArray(InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int read;
|
||||
byte[] slice = new byte[2000];
|
||||
while ( (read = inputStream.read(slice, 0, slice.length) ) != -1) {
|
||||
out.write( slice, 0, read );
|
||||
}
|
||||
out.flush();
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.hibernate.test.usertype;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class StringWrapper implements Serializable {
|
||||
|
||||
private final String value;
|
||||
|
||||
public StringWrapper(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StringWrapper that = (StringWrapper) o;
|
||||
|
||||
return value.equals( that.value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return value.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package org.hibernate.test.usertype;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.type.StringType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class StringWrapperUserType implements UserType {
|
||||
|
||||
public static final StringWrapperUserType INSTANCE = new StringWrapperUserType();
|
||||
|
||||
private static final Logger log = Logger.getLogger( StringWrapperUserType.class );
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes() {
|
||||
return new int[] {StringType.INSTANCE.sqlType()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class returnedClass() {
|
||||
return StringWrapper.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object x, Object y)
|
||||
throws HibernateException {
|
||||
return Objects.equals( x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(Object x)
|
||||
throws HibernateException {
|
||||
return Objects.hashCode( x );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(
|
||||
ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
String columnName = names[0];
|
||||
String columnValue = (String) rs.getObject( columnName );
|
||||
log.debugv("Result set column {0} value is {1}", columnName, columnValue);
|
||||
return columnValue == null ? null :
|
||||
fromString( columnValue );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(
|
||||
PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
if ( value == null ) {
|
||||
log.debugv("Binding null to parameter {0} ",index);
|
||||
st.setNull( index, Types.VARCHAR );
|
||||
}
|
||||
else {
|
||||
String stringValue = toString( (StringWrapper) value );
|
||||
log.debugv("Binding {0} to parameter {1} ", stringValue, index);
|
||||
st.setString( index, stringValue );
|
||||
}
|
||||
}
|
||||
public String toString(StringWrapper value) {
|
||||
return value.getValue();
|
||||
}
|
||||
|
||||
public StringWrapper fromString(String string) {
|
||||
if ( string == null || string.isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
return new StringWrapper( string );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object value)
|
||||
throws HibernateException {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable disassemble(Object value)
|
||||
throws HibernateException {
|
||||
return (StringWrapper) deepCopy( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object assemble(Serializable cached, Object owner)
|
||||
throws HibernateException {
|
||||
return deepCopy( cached );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object replace(Object original, Object target, Object owner)
|
||||
throws HibernateException {
|
||||
return deepCopy( original );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.usertype;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class StringWrapperUserTypeIntegrator implements Integrator {
|
||||
@Override
|
||||
public void integrate(
|
||||
Metadata metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
MetadataImplementor mi = (MetadataImplementor) metadata;
|
||||
mi.getTypeResolver().registerTypeOverride( StringWrapperUserType.INSTANCE, new String[] { StringWrapperUserType.INSTANCE.returnedClass().getName()});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
org.hibernate.test.service.TestIntegrator
|
||||
org.hibernate.test.usertype.StringWrapperUserTypeIntegrator
|
Loading…
Reference in New Issue