make it easy for Hibernate Reactive to reuse the @NaturalId stuff
This commit is contained in:
parent
e368ac5bab
commit
e0ee9f5b0a
|
@ -6,28 +6,15 @@
|
|||
*/
|
||||
package org.hibernate.loader.entity;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.type.AbstractType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Loads an entity instance using outerjoin fetching to fetch associated entities.
|
||||
* <br>
|
||||
|
@ -162,23 +149,14 @@ public class EntityLoader extends AbstractEntityLoader {
|
|||
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||
super( persister, new NaturalIdType( persister, valueNullness ), factory, loadQueryInfluencers );
|
||||
|
||||
EntityJoinWalker walker = new EntityJoinWalker(
|
||||
EntityJoinWalker walker = new NaturalIdEntityJoinWalker(
|
||||
persister,
|
||||
naturalIdColumns( valueNullness ),
|
||||
valueNullness,
|
||||
batchSize,
|
||||
lockOptions,
|
||||
factory,
|
||||
loadQueryInfluencers
|
||||
) {
|
||||
@Override
|
||||
protected StringBuilder whereString(String alias, String[] columnNames, int batchSize) {
|
||||
StringBuilder sql = super.whereString(alias, columnNames, batchSize);
|
||||
for (String nullCol : naturalIdColumns( ArrayHelper.negate( valueNullness ) ) ) {
|
||||
sql.append(" and ").append( getAlias() ).append('.').append(nullCol).append(" is null");
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
};
|
||||
);
|
||||
initFromWalker( walker );
|
||||
compositeKeyManyToOneTargetIndices = walker.getCompositeKeyManyToOneTargetIndices();
|
||||
postInstantiate();
|
||||
|
@ -194,17 +172,6 @@ public class EntityLoader extends AbstractEntityLoader {
|
|||
}
|
||||
}
|
||||
|
||||
private String[] naturalIdColumns(boolean[] valueNullness) {
|
||||
int i = 0;
|
||||
List<String> columns = new ArrayList<>();
|
||||
for ( int p : persister.getNaturalIdentifierProperties() ) {
|
||||
if ( !valueNullness[i++] ) {
|
||||
columns.addAll( Arrays.asList( persister.getPropertyColumnNames(p) ) );
|
||||
}
|
||||
}
|
||||
return columns.toArray(ArrayHelper.EMPTY_STRING_ARRAY);
|
||||
}
|
||||
|
||||
public Object loadByUniqueKey(SharedSessionContractImplementor session, Object key) {
|
||||
return loadByUniqueKey( session, key, null );
|
||||
}
|
||||
|
@ -223,117 +190,4 @@ public class EntityLoader extends AbstractEntityLoader {
|
|||
return compositeKeyManyToOneTargetIndices;
|
||||
}
|
||||
|
||||
static class NaturalIdType extends AbstractType {
|
||||
private OuterJoinLoadable persister;
|
||||
private boolean[] valueNullness;
|
||||
|
||||
NaturalIdType(OuterJoinLoadable persister, boolean[] valueNullness) {
|
||||
this.persister = persister;
|
||||
this.valueNullness = valueNullness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnSpan(Mapping mapping) throws MappingException {
|
||||
int span = 0;
|
||||
int i = 0;
|
||||
for ( int p : persister.getNaturalIdentifierProperties() ) {
|
||||
if ( !valueNullness[i++] ) {
|
||||
span += persister.getPropertyColumnNames(p).length;
|
||||
}
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes(Mapping mapping) throws MappingException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size[] dictatedSizes(Mapping mapping) throws MappingException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size[] defaultSizes(Mapping mapping) throws MappingException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnedClass() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object oldState, Object currentState, boolean[] checkable, SharedSessionContractImplementor session)
|
||||
throws HibernateException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
Object[] keys = (Object[]) value;
|
||||
int i = 0;
|
||||
for ( int p : persister.getNaturalIdentifierProperties() ) {
|
||||
if ( !valueNullness[i] ) {
|
||||
persister.getPropertyTypes()[p].nullSafeSet( st, keys[i], index++, session );
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toLoggableString(Object value, SessionFactoryImplementor factory) {
|
||||
return "natural id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object value, SessionFactoryImplementor factory) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map copyCache) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] toColumnNullness(Object value, Mapping mapping) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.loader.entity;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_STRING_ARRAY;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.negate;
|
||||
|
||||
/**
|
||||
* An {@link EntityJoinWalker} that uses 'is null' predicates to match
|
||||
* null {@link org.hibernate.annotations.NaturalId} properties.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class NaturalIdEntityJoinWalker extends EntityJoinWalker {
|
||||
|
||||
private static String[] naturalIdColumns(Loadable persister, boolean[] valueNullness) {
|
||||
int i = 0;
|
||||
List<String> columns = new ArrayList<>();
|
||||
for ( int p : persister.getNaturalIdentifierProperties() ) {
|
||||
if ( !valueNullness[i++] ) {
|
||||
columns.addAll( asList( persister.getPropertyColumnNames(p) ) );
|
||||
}
|
||||
}
|
||||
return columns.toArray(EMPTY_STRING_ARRAY);
|
||||
}
|
||||
|
||||
public NaturalIdEntityJoinWalker(
|
||||
OuterJoinLoadable persister,
|
||||
boolean[] valueNullness,
|
||||
int batchSize,
|
||||
LockOptions lockOptions,
|
||||
SessionFactoryImplementor factory,
|
||||
LoadQueryInfluencers loadQueryInfluencers) throws MappingException {
|
||||
super(persister, naturalIdColumns( persister, valueNullness ), batchSize, lockOptions, factory, loadQueryInfluencers);
|
||||
StringBuilder sql = new StringBuilder( getSQLString() );
|
||||
for ( String nullCol : naturalIdColumns( getPersister(), negate( valueNullness ) ) ) {
|
||||
sql.append(" and ").append( getAlias() ).append('.').append( nullCol ).append(" is null");
|
||||
}
|
||||
setSql( sql.toString() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* 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.loader.entity;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.type.AbstractType;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Workaround for the fact that we don't have a well-defined Hibernate
|
||||
* type when loading by multiple {@link org.hibernate.annotations.NaturalId}
|
||||
* properties.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class NaturalIdType extends AbstractType {
|
||||
private OuterJoinLoadable persister;
|
||||
private boolean[] valueNullness;
|
||||
|
||||
public NaturalIdType(OuterJoinLoadable persister, boolean[] valueNullness) {
|
||||
this.persister = persister;
|
||||
this.valueNullness = valueNullness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnSpan(Mapping mapping) throws MappingException {
|
||||
int span = 0;
|
||||
int i = 0;
|
||||
for (int p : persister.getNaturalIdentifierProperties() ) {
|
||||
if ( !valueNullness[i++] ) {
|
||||
span += persister.getPropertyColumnNames(p).length;
|
||||
}
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes(Mapping mapping) throws MappingException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size[] dictatedSizes(Mapping mapping) throws MappingException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size[] defaultSizes(Mapping mapping) throws MappingException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnedClass() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object oldState, Object currentState, boolean[] checkable, SharedSessionContractImplementor session)
|
||||
throws HibernateException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
Object[] keys = (Object[]) value;
|
||||
int i = 0;
|
||||
for ( int p : persister.getNaturalIdentifierProperties() ) {
|
||||
if ( !valueNullness[i] ) {
|
||||
persister.getPropertyTypes()[p].nullSafeSet( st, keys[i], index++, session );
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toLoggableString(Object value, SessionFactoryImplementor factory) {
|
||||
return "natural id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deepCopy(Object value, SessionFactoryImplementor factory) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map copyCache) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] toColumnNullness(Object value, Mapping mapping) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue