mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-08 12:14:47 +00:00
HHH-4440 : column-level read/write fragment support
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17821 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
d14de01220
commit
cb34e79283
@ -25,15 +25,12 @@
|
|||||||
package org.hibernate.cfg;
|
package org.hibernate.cfg;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.dom4j.Attribute;
|
import org.dom4j.Attribute;
|
||||||
import org.dom4j.Document;
|
import org.dom4j.Document;
|
||||||
import org.dom4j.Element;
|
import org.dom4j.Element;
|
||||||
@ -42,10 +39,10 @@
|
|||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.FlushMode;
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
||||||
import org.hibernate.engine.FilterDefinition;
|
import org.hibernate.engine.FilterDefinition;
|
||||||
import org.hibernate.engine.NamedQueryDefinition;
|
import org.hibernate.engine.NamedQueryDefinition;
|
||||||
import org.hibernate.engine.Versioning;
|
import org.hibernate.engine.Versioning;
|
||||||
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
|
||||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||||
import org.hibernate.mapping.Any;
|
import org.hibernate.mapping.Any;
|
||||||
import org.hibernate.mapping.Array;
|
import org.hibernate.mapping.Array;
|
||||||
@ -100,6 +97,8 @@
|
|||||||
import org.hibernate.util.JoinedIterator;
|
import org.hibernate.util.JoinedIterator;
|
||||||
import org.hibernate.util.ReflectHelper;
|
import org.hibernate.util.ReflectHelper;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walks an XML mapping document and produces the Hibernate configuration-time metamodel (the
|
* Walks an XML mapping document and produces the Hibernate configuration-time metamodel (the
|
||||||
@ -1705,7 +1704,7 @@ public static void bindOneToMany(Element node, OneToMany oneToMany, Mappings map
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bindColumn(Element node, Column column, boolean isNullable) {
|
public static void bindColumn(Element node, Column column, boolean isNullable) throws MappingException {
|
||||||
Attribute lengthNode = node.attribute( "length" );
|
Attribute lengthNode = node.attribute( "length" );
|
||||||
if ( lengthNode != null ) column.setLength( Integer.parseInt( lengthNode.getValue() ) );
|
if ( lengthNode != null ) column.setLength( Integer.parseInt( lengthNode.getValue() ) );
|
||||||
Attribute scalNode = node.attribute( "scale" );
|
Attribute scalNode = node.attribute( "scale" );
|
||||||
@ -1725,6 +1724,13 @@ public static void bindColumn(Element node, Column column, boolean isNullable) {
|
|||||||
Attribute typeNode = node.attribute( "sql-type" );
|
Attribute typeNode = node.attribute( "sql-type" );
|
||||||
if ( typeNode != null ) column.setSqlType( typeNode.getValue() );
|
if ( typeNode != null ) column.setSqlType( typeNode.getValue() );
|
||||||
|
|
||||||
|
String customWrite = node.attributeValue( "write" );
|
||||||
|
if(customWrite != null && !customWrite.matches("[^?]*\\?[^?]*")) {
|
||||||
|
throw new MappingException("write expression must contain exactly one value placeholder ('?') character");
|
||||||
|
}
|
||||||
|
column.setCustomWrite( customWrite );
|
||||||
|
column.setCustomRead( node.attributeValue( "read" ) );
|
||||||
|
|
||||||
Element comment = node.element("comment");
|
Element comment = node.element("comment");
|
||||||
if (comment!=null) column.setComment( comment.getTextTrim() );
|
if (comment!=null) column.setComment( comment.getTextTrim() );
|
||||||
|
|
||||||
|
@ -24,23 +24,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.lock;
|
package org.hibernate.dialect.lock;
|
||||||
|
|
||||||
import org.hibernate.persister.entity.Lockable;
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.StaleObjectStateException;
|
|
||||||
import org.hibernate.JDBCException;
|
|
||||||
import org.hibernate.pretty.MessageHelper;
|
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
|
||||||
import org.hibernate.sql.Update;
|
|
||||||
import org.hibernate.engine.SessionImplementor;
|
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.JDBCException;
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.StaleObjectStateException;
|
||||||
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.SessionImplementor;
|
||||||
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
|
import org.hibernate.persister.entity.Lockable;
|
||||||
|
import org.hibernate.pretty.MessageHelper;
|
||||||
|
import org.hibernate.sql.Update;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A locking strategy where the locks are obtained through update statements.
|
* A locking strategy where the locks are obtained through update statements.
|
||||||
* <p/>
|
* <p/>
|
||||||
@ -131,7 +131,7 @@ protected String generateLockString() {
|
|||||||
SessionFactoryImplementor factory = lockable.getFactory();
|
SessionFactoryImplementor factory = lockable.getFactory();
|
||||||
Update update = new Update( factory.getDialect() );
|
Update update = new Update( factory.getDialect() );
|
||||||
update.setTableName( lockable.getRootTableName() );
|
update.setTableName( lockable.getRootTableName() );
|
||||||
update.setPrimaryKeyColumnNames( lockable.getRootTableIdentifierColumnNames() );
|
update.addPrimaryKeyColumns( lockable.getRootTableIdentifierColumnNames() );
|
||||||
update.setVersionColumnName( lockable.getVersionColumnName() );
|
update.setVersionColumnName( lockable.getVersionColumnName() );
|
||||||
update.addColumn( lockable.getVersionColumnName() );
|
update.addColumn( lockable.getVersionColumnName() );
|
||||||
if ( factory.getSettings().isCommentsEnabled() ) {
|
if ( factory.getSettings().isCommentsEnabled() ) {
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.function.SQLFunctionRegistry;
|
import org.hibernate.dialect.function.SQLFunctionRegistry;
|
||||||
import org.hibernate.engine.Mapping;
|
import org.hibernate.engine.Mapping;
|
||||||
|
import org.hibernate.sql.Template;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,6 +59,8 @@ public class Column implements Selectable, Serializable, Cloneable {
|
|||||||
private String checkConstraint;
|
private String checkConstraint;
|
||||||
private String comment;
|
private String comment;
|
||||||
private String defaultValue;
|
private String defaultValue;
|
||||||
|
private String customWrite;
|
||||||
|
private String customRead;
|
||||||
|
|
||||||
public Column() { };
|
public Column() { };
|
||||||
|
|
||||||
@ -260,9 +263,18 @@ public boolean hasCheckConstraint() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getTemplate(Dialect dialect, SQLFunctionRegistry functionRegistry) {
|
public String getTemplate(Dialect dialect, SQLFunctionRegistry functionRegistry) {
|
||||||
return getQuotedName(dialect);
|
String expr = getReadExpr(dialect);
|
||||||
|
return Template.renderWhereStringTemplate(expr, dialect, functionRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getReadExpr(Dialect dialect) {
|
||||||
|
return ( customRead != null && customRead.length() > 0 ) ? customRead : getQuotedName(dialect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWriteExpr() {
|
||||||
|
return ( customWrite != null && customWrite.length() > 0 ) ? customWrite : "?";
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFormula() {
|
public boolean isFormula() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -304,6 +316,22 @@ public void setDefaultValue(String defaultValue) {
|
|||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCustomWrite() {
|
||||||
|
return customWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomWrite(String customWrite) {
|
||||||
|
this.customWrite = customWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCustomRead() {
|
||||||
|
return customRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomRead(String customRead) {
|
||||||
|
this.customRead = customRead;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCanonicalName() {
|
public String getCanonicalName() {
|
||||||
return quoted ? name : name.toLowerCase();
|
return quoted ? name : name.toLowerCase();
|
||||||
}
|
}
|
||||||
@ -327,6 +355,8 @@ protected Object clone() {
|
|||||||
copy.setCheckConstraint( checkConstraint );
|
copy.setCheckConstraint( checkConstraint );
|
||||||
copy.setComment( comment );
|
copy.setComment( comment );
|
||||||
copy.setDefaultValue( defaultValue );
|
copy.setDefaultValue( defaultValue );
|
||||||
|
copy.setCustomRead( customRead );
|
||||||
|
copy.setCustomWrite( customWrite );
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,16 +33,12 @@
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.TransientObjectException;
|
import org.hibernate.TransientObjectException;
|
||||||
import org.hibernate.jdbc.Expectation;
|
|
||||||
import org.hibernate.jdbc.Expectations;
|
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
|
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
|
||||||
import org.hibernate.cache.entry.CacheEntryStructure;
|
import org.hibernate.cache.entry.CacheEntryStructure;
|
||||||
@ -53,15 +49,17 @@
|
|||||||
import org.hibernate.collection.PersistentCollection;
|
import org.hibernate.collection.PersistentCollection;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.EntityKey;
|
import org.hibernate.engine.EntityKey;
|
||||||
|
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.PersistenceContext;
|
import org.hibernate.engine.PersistenceContext;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.engine.SubselectFetch;
|
import org.hibernate.engine.SubselectFetch;
|
||||||
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
|
||||||
import org.hibernate.engine.LoadQueryInfluencers;
|
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
import org.hibernate.exception.SQLExceptionConverter;
|
import org.hibernate.exception.SQLExceptionConverter;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
import org.hibernate.jdbc.Expectation;
|
||||||
|
import org.hibernate.jdbc.Expectations;
|
||||||
import org.hibernate.loader.collection.CollectionInitializer;
|
import org.hibernate.loader.collection.CollectionInitializer;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
@ -88,6 +86,8 @@
|
|||||||
import org.hibernate.util.ArrayHelper;
|
import org.hibernate.util.ArrayHelper;
|
||||||
import org.hibernate.util.FilterHelper;
|
import org.hibernate.util.FilterHelper;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,6 +140,9 @@ public abstract class AbstractCollectionPersister
|
|||||||
protected final String[] indexFormulas;
|
protected final String[] indexFormulas;
|
||||||
protected final boolean[] indexColumnIsSettable;
|
protected final boolean[] indexColumnIsSettable;
|
||||||
protected final String[] elementColumnNames;
|
protected final String[] elementColumnNames;
|
||||||
|
protected final String[] elementColumnWriters;
|
||||||
|
protected final String[] elementColumnReaders;
|
||||||
|
protected final String[] elementColumnReaderTemplates;
|
||||||
protected final String[] elementFormulaTemplates;
|
protected final String[] elementFormulaTemplates;
|
||||||
protected final String[] elementFormulas;
|
protected final String[] elementFormulas;
|
||||||
protected final boolean[] elementColumnIsSettable;
|
protected final boolean[] elementColumnIsSettable;
|
||||||
@ -320,6 +323,9 @@ public AbstractCollectionPersister(
|
|||||||
int elementSpan = collection.getElement().getColumnSpan();
|
int elementSpan = collection.getElement().getColumnSpan();
|
||||||
elementColumnAliases = new String[elementSpan];
|
elementColumnAliases = new String[elementSpan];
|
||||||
elementColumnNames = new String[elementSpan];
|
elementColumnNames = new String[elementSpan];
|
||||||
|
elementColumnWriters = new String[elementSpan];
|
||||||
|
elementColumnReaders = new String[elementSpan];
|
||||||
|
elementColumnReaderTemplates = new String[elementSpan];
|
||||||
elementFormulaTemplates = new String[elementSpan];
|
elementFormulaTemplates = new String[elementSpan];
|
||||||
elementFormulas = new String[elementSpan];
|
elementFormulas = new String[elementSpan];
|
||||||
elementColumnIsSettable = new boolean[elementSpan];
|
elementColumnIsSettable = new boolean[elementSpan];
|
||||||
@ -339,6 +345,9 @@ public AbstractCollectionPersister(
|
|||||||
else {
|
else {
|
||||||
Column col = (Column) selectable;
|
Column col = (Column) selectable;
|
||||||
elementColumnNames[j] = col.getQuotedName(dialect);
|
elementColumnNames[j] = col.getQuotedName(dialect);
|
||||||
|
elementColumnWriters[j] = col.getWriteExpr();
|
||||||
|
elementColumnReaders[j] = col.getReadExpr(dialect);
|
||||||
|
elementColumnReaderTemplates[j] = col.getTemplate(dialect, factory.getSqlFunctionRegistry());
|
||||||
elementColumnIsSettable[j] = true;
|
elementColumnIsSettable[j] = true;
|
||||||
elementColumnIsInPrimaryKey[j] = !col.isNullable();
|
elementColumnIsInPrimaryKey[j] = !col.isNullable();
|
||||||
if ( !col.isNullable() ) {
|
if ( !col.isNullable() ) {
|
||||||
@ -513,6 +522,8 @@ public AbstractCollectionPersister(
|
|||||||
if ( elementType.isComponentType() ) {
|
if ( elementType.isComponentType() ) {
|
||||||
elementPropertyMapping = new CompositeElementPropertyMapping(
|
elementPropertyMapping = new CompositeElementPropertyMapping(
|
||||||
elementColumnNames,
|
elementColumnNames,
|
||||||
|
elementColumnReaders,
|
||||||
|
elementColumnReaderTemplates,
|
||||||
elementFormulaTemplates,
|
elementFormulaTemplates,
|
||||||
(AbstractComponentType) elementType,
|
(AbstractComponentType) elementType,
|
||||||
factory
|
factory
|
||||||
@ -970,7 +981,7 @@ protected SelectFragment generateSelectFragment(String alias, String columnSuffi
|
|||||||
protected void appendElementColumns(SelectFragment frag, String elemAlias) {
|
protected void appendElementColumns(SelectFragment frag, String elemAlias) {
|
||||||
for ( int i=0; i<elementColumnIsSettable.length; i++ ) {
|
for ( int i=0; i<elementColumnIsSettable.length; i++ ) {
|
||||||
if ( elementColumnIsSettable[i] ) {
|
if ( elementColumnIsSettable[i] ) {
|
||||||
frag.addColumn( elemAlias, elementColumnNames[i], elementColumnAliases[i] );
|
frag.addColumnTemplate( elemAlias, elementColumnReaderTemplates[i], elementColumnAliases[i] );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
frag.addFormula( elemAlias, elementFormulaTemplates[i], elementColumnAliases[i] );
|
frag.addFormula( elemAlias, elementFormulaTemplates[i], elementColumnAliases[i] );
|
||||||
|
@ -31,10 +31,6 @@
|
|||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.jdbc.Expectations;
|
|
||||||
import org.hibernate.jdbc.Expectation;
|
|
||||||
import org.hibernate.type.AssociationType;
|
|
||||||
import org.hibernate.persister.entity.Joinable;
|
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
|
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
@ -44,15 +40,19 @@
|
|||||||
import org.hibernate.engine.SubselectFetch;
|
import org.hibernate.engine.SubselectFetch;
|
||||||
import org.hibernate.engine.LoadQueryInfluencers;
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
|
import org.hibernate.jdbc.Expectation;
|
||||||
|
import org.hibernate.jdbc.Expectations;
|
||||||
import org.hibernate.loader.collection.BatchingCollectionInitializer;
|
import org.hibernate.loader.collection.BatchingCollectionInitializer;
|
||||||
import org.hibernate.loader.collection.CollectionInitializer;
|
import org.hibernate.loader.collection.CollectionInitializer;
|
||||||
import org.hibernate.loader.collection.SubselectCollectionLoader;
|
import org.hibernate.loader.collection.SubselectCollectionLoader;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.sql.Delete;
|
import org.hibernate.sql.Delete;
|
||||||
import org.hibernate.sql.Insert;
|
import org.hibernate.sql.Insert;
|
||||||
import org.hibernate.sql.Update;
|
|
||||||
import org.hibernate.sql.SelectFragment;
|
import org.hibernate.sql.SelectFragment;
|
||||||
|
import org.hibernate.sql.Update;
|
||||||
|
import org.hibernate.type.AssociationType;
|
||||||
import org.hibernate.util.ArrayHelper;
|
import org.hibernate.util.ArrayHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,7 +81,7 @@ protected String generateDeleteString() {
|
|||||||
|
|
||||||
Delete delete = new Delete()
|
Delete delete = new Delete()
|
||||||
.setTableName( qualifiedTableName )
|
.setTableName( qualifiedTableName )
|
||||||
.setPrimaryKeyColumnNames( keyColumnNames );
|
.addPrimaryKeyColumns( keyColumnNames );
|
||||||
|
|
||||||
if ( hasWhere ) delete.setWhere( sqlWhereString );
|
if ( hasWhere ) delete.setWhere( sqlWhereString );
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ protected String generateInsertRowString() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if ( !elementIsFormula ) {
|
//if ( !elementIsFormula ) {
|
||||||
insert.addColumns( elementColumnNames, elementColumnIsSettable );
|
insert.addColumns( elementColumnNames, elementColumnIsSettable, elementColumnWriters );
|
||||||
//}
|
//}
|
||||||
|
|
||||||
return insert.toStatementString();
|
return insert.toStatementString();
|
||||||
@ -127,17 +127,18 @@ protected String generateUpdateRowString() {
|
|||||||
.setTableName( qualifiedTableName );
|
.setTableName( qualifiedTableName );
|
||||||
|
|
||||||
//if ( !elementIsFormula ) {
|
//if ( !elementIsFormula ) {
|
||||||
update.addColumns( elementColumnNames, elementColumnIsSettable );
|
update.addColumns( elementColumnNames, elementColumnIsSettable, elementColumnWriters );
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if ( hasIdentifier ) {
|
if ( hasIdentifier ) {
|
||||||
update.setPrimaryKeyColumnNames( new String[]{ identifierColumnName } );
|
update.addPrimaryKeyColumns( new String[]{ identifierColumnName } );
|
||||||
}
|
}
|
||||||
else if ( hasIndex && !indexContainsFormula ) {
|
else if ( hasIndex && !indexContainsFormula ) {
|
||||||
update.setPrimaryKeyColumnNames( ArrayHelper.join( keyColumnNames, indexColumnNames ) );
|
update.addPrimaryKeyColumns( ArrayHelper.join( keyColumnNames, indexColumnNames ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
update.setPrimaryKeyColumnNames( ArrayHelper.join( keyColumnNames, elementColumnNames, elementColumnIsInPrimaryKey ) );
|
update.addPrimaryKeyColumns( keyColumnNames );
|
||||||
|
update.addPrimaryKeyColumns( elementColumnNames, elementColumnIsInPrimaryKey, elementColumnWriters );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( getFactory().getSettings().isCommentsEnabled() ) {
|
if ( getFactory().getSettings().isCommentsEnabled() ) {
|
||||||
@ -156,13 +157,14 @@ protected String generateDeleteRowString() {
|
|||||||
.setTableName( qualifiedTableName );
|
.setTableName( qualifiedTableName );
|
||||||
|
|
||||||
if ( hasIdentifier ) {
|
if ( hasIdentifier ) {
|
||||||
delete.setPrimaryKeyColumnNames( new String[]{ identifierColumnName } );
|
delete.addPrimaryKeyColumns( new String[]{ identifierColumnName } );
|
||||||
}
|
}
|
||||||
else if ( hasIndex && !indexContainsFormula ) {
|
else if ( hasIndex && !indexContainsFormula ) {
|
||||||
delete.setPrimaryKeyColumnNames( ArrayHelper.join( keyColumnNames, indexColumnNames ) );
|
delete.addPrimaryKeyColumns( ArrayHelper.join( keyColumnNames, indexColumnNames ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
delete.setPrimaryKeyColumnNames( ArrayHelper.join( keyColumnNames, elementColumnNames, elementColumnIsInPrimaryKey ) );
|
delete.addPrimaryKeyColumns( keyColumnNames );
|
||||||
|
delete.addPrimaryKeyColumns( elementColumnNames, elementColumnIsInPrimaryKey, elementColumnWriters );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( getFactory().getSettings().isCommentsEnabled() ) {
|
if ( getFactory().getSettings().isCommentsEnabled() ) {
|
||||||
|
@ -38,7 +38,9 @@ public class CompositeElementPropertyMapping extends AbstractPropertyMapping {
|
|||||||
private final AbstractComponentType compositeType;
|
private final AbstractComponentType compositeType;
|
||||||
|
|
||||||
public CompositeElementPropertyMapping(
|
public CompositeElementPropertyMapping(
|
||||||
String[] elementColumns,
|
String[] elementColumns,
|
||||||
|
String[] elementColumnReaders,
|
||||||
|
String[] elementColumnReaderTemplates,
|
||||||
String[] elementFormulaTemplates,
|
String[] elementFormulaTemplates,
|
||||||
AbstractComponentType compositeType,
|
AbstractComponentType compositeType,
|
||||||
Mapping factory)
|
Mapping factory)
|
||||||
@ -46,7 +48,8 @@ public CompositeElementPropertyMapping(
|
|||||||
|
|
||||||
this.compositeType = compositeType;
|
this.compositeType = compositeType;
|
||||||
|
|
||||||
initComponentPropertyPaths(null, compositeType, elementColumns, elementFormulaTemplates, factory);
|
initComponentPropertyPaths(null, compositeType, elementColumns, elementColumnReaders,
|
||||||
|
elementColumnReaderTemplates, elementFormulaTemplates, factory);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,4 +61,4 @@ protected String getEntityName() {
|
|||||||
return compositeType.getName();
|
return compositeType.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.jdbc.Expectation;
|
|
||||||
import org.hibernate.jdbc.Expectations;
|
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
|
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
@ -42,6 +40,8 @@
|
|||||||
import org.hibernate.engine.SubselectFetch;
|
import org.hibernate.engine.SubselectFetch;
|
||||||
import org.hibernate.engine.LoadQueryInfluencers;
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
|
import org.hibernate.jdbc.Expectation;
|
||||||
|
import org.hibernate.jdbc.Expectations;
|
||||||
import org.hibernate.loader.collection.BatchingCollectionInitializer;
|
import org.hibernate.loader.collection.BatchingCollectionInitializer;
|
||||||
import org.hibernate.loader.collection.CollectionInitializer;
|
import org.hibernate.loader.collection.CollectionInitializer;
|
||||||
import org.hibernate.loader.collection.SubselectOneToManyLoader;
|
import org.hibernate.loader.collection.SubselectOneToManyLoader;
|
||||||
@ -96,7 +96,7 @@ protected String generateDeleteString() {
|
|||||||
Update update = new Update( getDialect() )
|
Update update = new Update( getDialect() )
|
||||||
.setTableName( qualifiedTableName )
|
.setTableName( qualifiedTableName )
|
||||||
.addColumns( keyColumnNames, "null" )
|
.addColumns( keyColumnNames, "null" )
|
||||||
.setPrimaryKeyColumnNames( keyColumnNames );
|
.addPrimaryKeyColumns( keyColumnNames );
|
||||||
|
|
||||||
if ( hasIndex && !indexContainsFormula ) update.addColumns( indexColumnNames, "null" );
|
if ( hasIndex && !indexContainsFormula ) update.addColumns( indexColumnNames, "null" );
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ protected String generateInsertRowString() {
|
|||||||
update.setComment( "create one-to-many row " + getRole() );
|
update.setComment( "create one-to-many row " + getRole() );
|
||||||
}
|
}
|
||||||
|
|
||||||
return update.setPrimaryKeyColumnNames( elementColumnNames )
|
return update.addPrimaryKeyColumns( elementColumnNames, elementColumnWriters )
|
||||||
.toStatementString();
|
.toStatementString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ protected String generateDeleteRowString() {
|
|||||||
//the ordering of removal and addition is not guaranteed when
|
//the ordering of removal and addition is not guaranteed when
|
||||||
//a child moves from one parent to another
|
//a child moves from one parent to another
|
||||||
String[] rowSelectColumnNames = ArrayHelper.join(keyColumnNames, elementColumnNames);
|
String[] rowSelectColumnNames = ArrayHelper.join(keyColumnNames, elementColumnNames);
|
||||||
return update.setPrimaryKeyColumnNames( rowSelectColumnNames )
|
return update.addPrimaryKeyColumns( rowSelectColumnNames )
|
||||||
.toStatementString();
|
.toStatementString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,15 +30,13 @@
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
@ -48,36 +46,36 @@
|
|||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.StaleObjectStateException;
|
import org.hibernate.StaleObjectStateException;
|
||||||
import org.hibernate.StaleStateException;
|
import org.hibernate.StaleStateException;
|
||||||
import org.hibernate.jdbc.Expectation;
|
|
||||||
import org.hibernate.jdbc.Expectations;
|
|
||||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
|
||||||
import org.hibernate.cache.CacheKey;
|
import org.hibernate.cache.CacheKey;
|
||||||
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
||||||
import org.hibernate.cache.entry.CacheEntry;
|
import org.hibernate.cache.entry.CacheEntry;
|
||||||
import org.hibernate.cache.entry.CacheEntryStructure;
|
import org.hibernate.cache.entry.CacheEntryStructure;
|
||||||
import org.hibernate.cache.entry.StructuredCacheEntry;
|
import org.hibernate.cache.entry.StructuredCacheEntry;
|
||||||
import org.hibernate.cache.entry.UnstructuredCacheEntry;
|
import org.hibernate.cache.entry.UnstructuredCacheEntry;
|
||||||
|
import org.hibernate.dialect.lock.LockingStrategy;
|
||||||
import org.hibernate.engine.CascadeStyle;
|
import org.hibernate.engine.CascadeStyle;
|
||||||
import org.hibernate.engine.CascadingAction;
|
import org.hibernate.engine.CascadingAction;
|
||||||
import org.hibernate.engine.EntityEntry;
|
import org.hibernate.engine.EntityEntry;
|
||||||
|
import org.hibernate.engine.EntityKey;
|
||||||
|
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
||||||
|
import org.hibernate.engine.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.Mapping;
|
import org.hibernate.engine.Mapping;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.engine.Versioning;
|
|
||||||
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
|
||||||
import org.hibernate.engine.EntityKey;
|
|
||||||
import org.hibernate.engine.ValueInclusion;
|
import org.hibernate.engine.ValueInclusion;
|
||||||
import org.hibernate.engine.LoadQueryInfluencers;
|
import org.hibernate.engine.Versioning;
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
import org.hibernate.id.PostInsertIdentifierGenerator;
|
import org.hibernate.id.PostInsertIdentifierGenerator;
|
||||||
import org.hibernate.id.PostInsertIdentityPersister;
|
import org.hibernate.id.PostInsertIdentityPersister;
|
||||||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
|
||||||
import org.hibernate.id.insert.Binder;
|
import org.hibernate.id.insert.Binder;
|
||||||
import org.hibernate.intercept.LazyPropertyInitializer;
|
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||||
import org.hibernate.intercept.FieldInterceptionHelper;
|
import org.hibernate.intercept.FieldInterceptionHelper;
|
||||||
import org.hibernate.intercept.FieldInterceptor;
|
import org.hibernate.intercept.FieldInterceptor;
|
||||||
|
import org.hibernate.intercept.LazyPropertyInitializer;
|
||||||
|
import org.hibernate.jdbc.Expectation;
|
||||||
|
import org.hibernate.jdbc.Expectations;
|
||||||
|
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||||
import org.hibernate.loader.entity.BatchingEntityLoader;
|
import org.hibernate.loader.entity.BatchingEntityLoader;
|
||||||
import org.hibernate.loader.entity.CascadeEntityLoader;
|
import org.hibernate.loader.entity.CascadeEntityLoader;
|
||||||
import org.hibernate.loader.entity.EntityLoader;
|
import org.hibernate.loader.entity.EntityLoader;
|
||||||
@ -99,10 +97,9 @@
|
|||||||
import org.hibernate.sql.SimpleSelect;
|
import org.hibernate.sql.SimpleSelect;
|
||||||
import org.hibernate.sql.Template;
|
import org.hibernate.sql.Template;
|
||||||
import org.hibernate.sql.Update;
|
import org.hibernate.sql.Update;
|
||||||
import org.hibernate.sql.AliasGenerator;
|
import org.hibernate.tuple.Tuplizer;
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||||
import org.hibernate.tuple.Tuplizer;
|
|
||||||
import org.hibernate.type.AbstractComponentType;
|
import org.hibernate.type.AbstractComponentType;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
@ -112,6 +109,8 @@
|
|||||||
import org.hibernate.util.ArrayHelper;
|
import org.hibernate.util.ArrayHelper;
|
||||||
import org.hibernate.util.FilterHelper;
|
import org.hibernate.util.FilterHelper;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic functionality for persisting an entity via JDBC
|
* Basic functionality for persisting an entity via JDBC
|
||||||
@ -136,6 +135,8 @@ public abstract class AbstractEntityPersister
|
|||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
private final String[] rootTableKeyColumnNames;
|
private final String[] rootTableKeyColumnNames;
|
||||||
|
private final String[] rootTableKeyColumnReaders;
|
||||||
|
private final String[] rootTableKeyColumnReaderTemplates;
|
||||||
private final String[] identifierAliases;
|
private final String[] identifierAliases;
|
||||||
private final int identifierColumnSpan;
|
private final int identifierColumnSpan;
|
||||||
private final String versionColumnName;
|
private final String versionColumnName;
|
||||||
@ -158,6 +159,8 @@ public abstract class AbstractEntityPersister
|
|||||||
private final String[][] propertyColumnAliases;
|
private final String[][] propertyColumnAliases;
|
||||||
private final String[][] propertyColumnNames;
|
private final String[][] propertyColumnNames;
|
||||||
private final String[][] propertyColumnFormulaTemplates;
|
private final String[][] propertyColumnFormulaTemplates;
|
||||||
|
private final String[][] propertyColumnReaderTemplates;
|
||||||
|
private final String[][] propertyColumnWriters;
|
||||||
private final boolean[][] propertyColumnUpdateable;
|
private final boolean[][] propertyColumnUpdateable;
|
||||||
private final boolean[][] propertyColumnInsertable;
|
private final boolean[][] propertyColumnInsertable;
|
||||||
private final boolean[] propertyUniqueness;
|
private final boolean[] propertyUniqueness;
|
||||||
@ -175,6 +178,8 @@ public abstract class AbstractEntityPersister
|
|||||||
private final Type[] subclassPropertyTypeClosure;
|
private final Type[] subclassPropertyTypeClosure;
|
||||||
private final String[][] subclassPropertyFormulaTemplateClosure;
|
private final String[][] subclassPropertyFormulaTemplateClosure;
|
||||||
private final String[][] subclassPropertyColumnNameClosure;
|
private final String[][] subclassPropertyColumnNameClosure;
|
||||||
|
private final String[][] subclassPropertyColumnReaderClosure;
|
||||||
|
private final String[][] subclassPropertyColumnReaderTemplateClosure;
|
||||||
private final FetchMode[] subclassPropertyFetchModeClosure;
|
private final FetchMode[] subclassPropertyFetchModeClosure;
|
||||||
private final boolean[] subclassPropertyNullabilityClosure;
|
private final boolean[] subclassPropertyNullabilityClosure;
|
||||||
private final boolean[] propertyDefinedOnSubclass;
|
private final boolean[] propertyDefinedOnSubclass;
|
||||||
@ -187,6 +192,7 @@ public abstract class AbstractEntityPersister
|
|||||||
private final boolean[] subclassColumnLazyClosure;
|
private final boolean[] subclassColumnLazyClosure;
|
||||||
private final String[] subclassColumnAliasClosure;
|
private final String[] subclassColumnAliasClosure;
|
||||||
private final boolean[] subclassColumnSelectableClosure;
|
private final boolean[] subclassColumnSelectableClosure;
|
||||||
|
private final String[] subclassColumnReaderTemplateClosure;
|
||||||
private final String[] subclassFormulaClosure;
|
private final String[] subclassFormulaClosure;
|
||||||
private final String[] subclassFormulaTemplateClosure;
|
private final String[] subclassFormulaTemplateClosure;
|
||||||
private final String[] subclassFormulaAliasClosure;
|
private final String[] subclassFormulaAliasClosure;
|
||||||
@ -285,6 +291,14 @@ public String getDiscriminatorColumnName() {
|
|||||||
return DISCRIMINATOR_ALIAS;
|
return DISCRIMINATOR_ALIAS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDiscriminatorColumnReaders() {
|
||||||
|
return DISCRIMINATOR_ALIAS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDiscriminatorColumnReaderTemplate() {
|
||||||
|
return DISCRIMINATOR_ALIAS;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getDiscriminatorAlias() {
|
protected String getDiscriminatorAlias() {
|
||||||
return DISCRIMINATOR_ALIAS;
|
return DISCRIMINATOR_ALIAS;
|
||||||
}
|
}
|
||||||
@ -471,6 +485,8 @@ public AbstractEntityPersister(
|
|||||||
|
|
||||||
identifierColumnSpan = persistentClass.getIdentifier().getColumnSpan();
|
identifierColumnSpan = persistentClass.getIdentifier().getColumnSpan();
|
||||||
rootTableKeyColumnNames = new String[identifierColumnSpan];
|
rootTableKeyColumnNames = new String[identifierColumnSpan];
|
||||||
|
rootTableKeyColumnReaders = new String[identifierColumnSpan];
|
||||||
|
rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan];
|
||||||
identifierAliases = new String[identifierColumnSpan];
|
identifierAliases = new String[identifierColumnSpan];
|
||||||
|
|
||||||
rowIdName = persistentClass.getRootTable().getRowId();
|
rowIdName = persistentClass.getRootTable().getRowId();
|
||||||
@ -482,6 +498,8 @@ public AbstractEntityPersister(
|
|||||||
while ( iter.hasNext() ) {
|
while ( iter.hasNext() ) {
|
||||||
Column col = ( Column ) iter.next();
|
Column col = ( Column ) iter.next();
|
||||||
rootTableKeyColumnNames[i] = col.getQuotedName( factory.getDialect() );
|
rootTableKeyColumnNames[i] = col.getQuotedName( factory.getDialect() );
|
||||||
|
rootTableKeyColumnReaders[i] = col.getReadExpr( factory.getDialect() );
|
||||||
|
rootTableKeyColumnReaderTemplates[i] = col.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||||
identifierAliases[i] = col.getAlias( factory.getDialect(), persistentClass.getRootTable() );
|
identifierAliases[i] = col.getAlias( factory.getDialect(), persistentClass.getRootTable() );
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -512,6 +530,8 @@ public AbstractEntityPersister(
|
|||||||
propertyColumnAliases = new String[hydrateSpan][];
|
propertyColumnAliases = new String[hydrateSpan][];
|
||||||
propertyColumnNames = new String[hydrateSpan][];
|
propertyColumnNames = new String[hydrateSpan][];
|
||||||
propertyColumnFormulaTemplates = new String[hydrateSpan][];
|
propertyColumnFormulaTemplates = new String[hydrateSpan][];
|
||||||
|
propertyColumnReaderTemplates = new String[hydrateSpan][];
|
||||||
|
propertyColumnWriters = new String[hydrateSpan][];
|
||||||
propertyUniqueness = new boolean[hydrateSpan];
|
propertyUniqueness = new boolean[hydrateSpan];
|
||||||
propertySelectable = new boolean[hydrateSpan];
|
propertySelectable = new boolean[hydrateSpan];
|
||||||
propertyColumnUpdateable = new boolean[hydrateSpan][];
|
propertyColumnUpdateable = new boolean[hydrateSpan][];
|
||||||
@ -536,7 +556,9 @@ public AbstractEntityPersister(
|
|||||||
propertySubclassNames[i] = prop.getPersistentClass().getEntityName();
|
propertySubclassNames[i] = prop.getPersistentClass().getEntityName();
|
||||||
String[] colNames = new String[span];
|
String[] colNames = new String[span];
|
||||||
String[] colAliases = new String[span];
|
String[] colAliases = new String[span];
|
||||||
String[] templates = new String[span];
|
String[] colReaderTemplates = new String[span];
|
||||||
|
String[] colWriters = new String[span];
|
||||||
|
String[] formulaTemplates = new String[span];
|
||||||
Iterator colIter = prop.getColumnIterator();
|
Iterator colIter = prop.getColumnIterator();
|
||||||
int k = 0;
|
int k = 0;
|
||||||
while ( colIter.hasNext() ) {
|
while ( colIter.hasNext() ) {
|
||||||
@ -544,15 +566,20 @@ public AbstractEntityPersister(
|
|||||||
colAliases[k] = thing.getAlias( factory.getDialect() , prop.getValue().getTable() );
|
colAliases[k] = thing.getAlias( factory.getDialect() , prop.getValue().getTable() );
|
||||||
if ( thing.isFormula() ) {
|
if ( thing.isFormula() ) {
|
||||||
foundFormula = true;
|
foundFormula = true;
|
||||||
templates[k] = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
formulaTemplates[k] = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
colNames[k] = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
Column col = (Column)thing;
|
||||||
|
colNames[k] = col.getQuotedName( factory.getDialect() );
|
||||||
|
colReaderTemplates[k] = col.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||||
|
colWriters[k] = col.getWriteExpr();
|
||||||
}
|
}
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
propertyColumnNames[i] = colNames;
|
propertyColumnNames[i] = colNames;
|
||||||
propertyColumnFormulaTemplates[i] = templates;
|
propertyColumnFormulaTemplates[i] = formulaTemplates;
|
||||||
|
propertyColumnReaderTemplates[i] = colReaderTemplates;
|
||||||
|
propertyColumnWriters[i] = colWriters;
|
||||||
propertyColumnAliases[i] = colAliases;
|
propertyColumnAliases[i] = colAliases;
|
||||||
|
|
||||||
if ( lazyAvailable && prop.isLazy() ) {
|
if ( lazyAvailable && prop.isLazy() ) {
|
||||||
@ -583,6 +610,7 @@ public AbstractEntityPersister(
|
|||||||
|
|
||||||
ArrayList columns = new ArrayList();
|
ArrayList columns = new ArrayList();
|
||||||
ArrayList columnsLazy = new ArrayList();
|
ArrayList columnsLazy = new ArrayList();
|
||||||
|
ArrayList columnReaderTemplates = new ArrayList();
|
||||||
ArrayList aliases = new ArrayList();
|
ArrayList aliases = new ArrayList();
|
||||||
ArrayList formulas = new ArrayList();
|
ArrayList formulas = new ArrayList();
|
||||||
ArrayList formulaAliases = new ArrayList();
|
ArrayList formulaAliases = new ArrayList();
|
||||||
@ -593,6 +621,8 @@ public AbstractEntityPersister(
|
|||||||
ArrayList classes = new ArrayList();
|
ArrayList classes = new ArrayList();
|
||||||
ArrayList templates = new ArrayList();
|
ArrayList templates = new ArrayList();
|
||||||
ArrayList propColumns = new ArrayList();
|
ArrayList propColumns = new ArrayList();
|
||||||
|
ArrayList propColumnReaders = new ArrayList();
|
||||||
|
ArrayList propColumnReaderTemplates = new ArrayList();
|
||||||
ArrayList joinedFetchesList = new ArrayList();
|
ArrayList joinedFetchesList = new ArrayList();
|
||||||
ArrayList cascades = new ArrayList();
|
ArrayList cascades = new ArrayList();
|
||||||
ArrayList definedBySubclass = new ArrayList();
|
ArrayList definedBySubclass = new ArrayList();
|
||||||
@ -613,6 +643,8 @@ public AbstractEntityPersister(
|
|||||||
|
|
||||||
Iterator colIter = prop.getColumnIterator();
|
Iterator colIter = prop.getColumnIterator();
|
||||||
String[] cols = new String[prop.getColumnSpan()];
|
String[] cols = new String[prop.getColumnSpan()];
|
||||||
|
String[] readers = new String[prop.getColumnSpan()];
|
||||||
|
String[] readerTemplates = new String[prop.getColumnSpan()];
|
||||||
String[] forms = new String[prop.getColumnSpan()];
|
String[] forms = new String[prop.getColumnSpan()];
|
||||||
int[] colnos = new int[prop.getColumnSpan()];
|
int[] colnos = new int[prop.getColumnSpan()];
|
||||||
int[] formnos = new int[prop.getColumnSpan()];
|
int[] formnos = new int[prop.getColumnSpan()];
|
||||||
@ -631,7 +663,8 @@ public AbstractEntityPersister(
|
|||||||
formulasLazy.add( lazy );
|
formulasLazy.add( lazy );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String colName = thing.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
Column col = (Column)thing;
|
||||||
|
String colName = col.getQuotedName( factory.getDialect() );
|
||||||
colnos[l] = columns.size(); //before add :-)
|
colnos[l] = columns.size(); //before add :-)
|
||||||
formnos[l] = -1;
|
formnos[l] = -1;
|
||||||
columns.add( colName );
|
columns.add( colName );
|
||||||
@ -639,10 +672,17 @@ public AbstractEntityPersister(
|
|||||||
aliases.add( thing.getAlias( factory.getDialect(), prop.getValue().getTable() ) );
|
aliases.add( thing.getAlias( factory.getDialect(), prop.getValue().getTable() ) );
|
||||||
columnsLazy.add( lazy );
|
columnsLazy.add( lazy );
|
||||||
columnSelectables.add( Boolean.valueOf( prop.isSelectable() ) );
|
columnSelectables.add( Boolean.valueOf( prop.isSelectable() ) );
|
||||||
|
|
||||||
|
readers[l] = col.getReadExpr( factory.getDialect() );
|
||||||
|
String readerTemplate = col.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||||
|
readerTemplates[l] = readerTemplate;
|
||||||
|
columnReaderTemplates.add( readerTemplate );
|
||||||
}
|
}
|
||||||
l++;
|
l++;
|
||||||
}
|
}
|
||||||
propColumns.add( cols );
|
propColumns.add( cols );
|
||||||
|
propColumnReaders.add( readers );
|
||||||
|
propColumnReaderTemplates.add( readerTemplates );
|
||||||
templates.add( forms );
|
templates.add( forms );
|
||||||
propColumnNumbers.add( colnos );
|
propColumnNumbers.add( colnos );
|
||||||
propFormulaNumbers.add( formnos );
|
propFormulaNumbers.add( formnos );
|
||||||
@ -654,6 +694,7 @@ public AbstractEntityPersister(
|
|||||||
subclassColumnAliasClosure = ArrayHelper.toStringArray( aliases );
|
subclassColumnAliasClosure = ArrayHelper.toStringArray( aliases );
|
||||||
subclassColumnLazyClosure = ArrayHelper.toBooleanArray( columnsLazy );
|
subclassColumnLazyClosure = ArrayHelper.toBooleanArray( columnsLazy );
|
||||||
subclassColumnSelectableClosure = ArrayHelper.toBooleanArray( columnSelectables );
|
subclassColumnSelectableClosure = ArrayHelper.toBooleanArray( columnSelectables );
|
||||||
|
subclassColumnReaderTemplateClosure = ArrayHelper.toStringArray( columnReaderTemplates );
|
||||||
|
|
||||||
subclassFormulaClosure = ArrayHelper.toStringArray( formulas );
|
subclassFormulaClosure = ArrayHelper.toStringArray( formulas );
|
||||||
subclassFormulaTemplateClosure = ArrayHelper.toStringArray( formulaTemplates );
|
subclassFormulaTemplateClosure = ArrayHelper.toStringArray( formulaTemplates );
|
||||||
@ -666,6 +707,8 @@ public AbstractEntityPersister(
|
|||||||
subclassPropertyNullabilityClosure = ArrayHelper.toBooleanArray( propNullables );
|
subclassPropertyNullabilityClosure = ArrayHelper.toBooleanArray( propNullables );
|
||||||
subclassPropertyFormulaTemplateClosure = ArrayHelper.to2DStringArray( templates );
|
subclassPropertyFormulaTemplateClosure = ArrayHelper.to2DStringArray( templates );
|
||||||
subclassPropertyColumnNameClosure = ArrayHelper.to2DStringArray( propColumns );
|
subclassPropertyColumnNameClosure = ArrayHelper.to2DStringArray( propColumns );
|
||||||
|
subclassPropertyColumnReaderClosure = ArrayHelper.to2DStringArray( propColumnReaders );
|
||||||
|
subclassPropertyColumnReaderTemplateClosure = ArrayHelper.to2DStringArray( propColumnReaderTemplates );
|
||||||
subclassPropertyColumnNumberClosure = ArrayHelper.to2DIntArray( propColumnNumbers );
|
subclassPropertyColumnNumberClosure = ArrayHelper.to2DIntArray( propColumnNumbers );
|
||||||
subclassPropertyFormulaNumberClosure = ArrayHelper.to2DIntArray( propFormulaNumbers );
|
subclassPropertyFormulaNumberClosure = ArrayHelper.to2DIntArray( propFormulaNumbers );
|
||||||
|
|
||||||
@ -906,6 +949,14 @@ public String[] getIdentifierColumnNames() {
|
|||||||
return rootTableKeyColumnNames;
|
return rootTableKeyColumnNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getIdentifierColumnReaders() {
|
||||||
|
return rootTableKeyColumnReaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getIdentifierColumnReaderTemplates() {
|
||||||
|
return rootTableKeyColumnReaderTemplates;
|
||||||
|
}
|
||||||
|
|
||||||
protected int getIdentifierColumnSpan() {
|
protected int getIdentifierColumnSpan() {
|
||||||
return identifierColumnSpan;
|
return identifierColumnSpan;
|
||||||
}
|
}
|
||||||
@ -997,14 +1048,14 @@ public SelectFragment propertySelectFragmentFragment(
|
|||||||
|
|
||||||
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
|
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
|
||||||
String[] columnAliases = getSubclassColumnAliasClosure();
|
String[] columnAliases = getSubclassColumnAliasClosure();
|
||||||
String[] columns = getSubclassColumnClosure();
|
String[] columnReaderTemplates = getSubclassColumnReaderTemplateClosure();
|
||||||
for ( int i = 0; i < getSubclassColumnClosure().length; i++ ) {
|
for ( int i = 0; i < getSubclassColumnClosure().length; i++ ) {
|
||||||
boolean selectable = ( allProperties || !subclassColumnLazyClosure[i] ) &&
|
boolean selectable = ( allProperties || !subclassColumnLazyClosure[i] ) &&
|
||||||
!isSubclassTableSequentialSelect( columnTableNumbers[i] ) &&
|
!isSubclassTableSequentialSelect( columnTableNumbers[i] ) &&
|
||||||
subclassColumnSelectableClosure[i];
|
subclassColumnSelectableClosure[i];
|
||||||
if ( selectable ) {
|
if ( selectable ) {
|
||||||
String subalias = generateTableAlias( tableAlias, columnTableNumbers[i] );
|
String subalias = generateTableAlias( tableAlias, columnTableNumbers[i] );
|
||||||
select.addColumn( subalias, columns[i], columnAliases[i] );
|
select.addColumnTemplate( subalias, columnReaderTemplates[i], columnAliases[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1174,9 +1225,9 @@ protected String concretePropertySelectFragment(String alias, InclusionChecker i
|
|||||||
SelectFragment frag = new SelectFragment();
|
SelectFragment frag = new SelectFragment();
|
||||||
for ( int i = 0; i < propertyCount; i++ ) {
|
for ( int i = 0; i < propertyCount; i++ ) {
|
||||||
if ( inclusionChecker.includeProperty( i ) ) {
|
if ( inclusionChecker.includeProperty( i ) ) {
|
||||||
frag.addColumns(
|
frag.addColumnTemplates(
|
||||||
generateTableAlias( alias, propertyTableNumbers[i] ),
|
generateTableAlias( alias, propertyTableNumbers[i] ),
|
||||||
propertyColumnNames[i],
|
propertyColumnReaderTemplates[i],
|
||||||
propertyColumnAliases[i]
|
propertyColumnAliases[i]
|
||||||
);
|
);
|
||||||
frag.addFormulas(
|
frag.addFormulas(
|
||||||
@ -1284,7 +1335,7 @@ private String generateVersionIncrementUpdateString() {
|
|||||||
update.setComment( "forced version increment" );
|
update.setComment( "forced version increment" );
|
||||||
}
|
}
|
||||||
update.addColumn( getVersionColumnName() );
|
update.addColumn( getVersionColumnName() );
|
||||||
update.setPrimaryKeyColumnNames( getIdentifierColumnNames() );
|
update.addPrimaryKeyColumns( getIdentifierColumnNames() );
|
||||||
update.setVersionColumnName( getVersionColumnName() );
|
update.setVersionColumnName( getVersionColumnName() );
|
||||||
return update.toStatementString();
|
return update.toStatementString();
|
||||||
}
|
}
|
||||||
@ -1472,6 +1523,10 @@ protected String[] getPropertySubclassNames() {
|
|||||||
public String[] getPropertyColumnNames(int i) {
|
public String[] getPropertyColumnNames(int i) {
|
||||||
return propertyColumnNames[i];
|
return propertyColumnNames[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getPropertyColumnWriters(int i) {
|
||||||
|
return propertyColumnWriters[i];
|
||||||
|
}
|
||||||
|
|
||||||
protected int getPropertyColumnSpan(int i) {
|
protected int getPropertyColumnSpan(int i) {
|
||||||
return propertyColumnSpans[i];
|
return propertyColumnSpans[i];
|
||||||
@ -1520,6 +1575,14 @@ protected Type[] getSubclassPropertyTypeClosure() {
|
|||||||
protected String[][] getSubclassPropertyColumnNameClosure() {
|
protected String[][] getSubclassPropertyColumnNameClosure() {
|
||||||
return subclassPropertyColumnNameClosure;
|
return subclassPropertyColumnNameClosure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[][] getSubclassPropertyColumnReaderClosure() {
|
||||||
|
return subclassPropertyColumnReaderClosure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] getSubclassPropertyColumnReaderTemplateClosure() {
|
||||||
|
return subclassPropertyColumnReaderTemplateClosure;
|
||||||
|
}
|
||||||
|
|
||||||
protected String[] getSubclassPropertyNameClosure() {
|
protected String[] getSubclassPropertyNameClosure() {
|
||||||
return subclassPropertyNameClosure;
|
return subclassPropertyNameClosure;
|
||||||
@ -1537,6 +1600,10 @@ protected String[] getSubclassColumnAliasClosure() {
|
|||||||
return subclassColumnAliasClosure;
|
return subclassColumnAliasClosure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getSubclassColumnReaderTemplateClosure() {
|
||||||
|
return subclassColumnReaderTemplateClosure;
|
||||||
|
}
|
||||||
|
|
||||||
protected String[] getSubclassFormulaClosure() {
|
protected String[] getSubclassFormulaClosure() {
|
||||||
return subclassFormulaClosure;
|
return subclassFormulaClosure;
|
||||||
}
|
}
|
||||||
@ -1744,6 +1811,8 @@ private void initOrdinaryPropertyPaths(Mapping mapping) throws MappingException
|
|||||||
propertyMapping.initPropertyPaths( getSubclassPropertyNameClosure()[i],
|
propertyMapping.initPropertyPaths( getSubclassPropertyNameClosure()[i],
|
||||||
getSubclassPropertyTypeClosure()[i],
|
getSubclassPropertyTypeClosure()[i],
|
||||||
getSubclassPropertyColumnNameClosure()[i],
|
getSubclassPropertyColumnNameClosure()[i],
|
||||||
|
getSubclassPropertyColumnReaderClosure()[i],
|
||||||
|
getSubclassPropertyColumnReaderTemplateClosure()[i],
|
||||||
getSubclassPropertyFormulaTemplateClosure()[i],
|
getSubclassPropertyFormulaTemplateClosure()[i],
|
||||||
mapping );
|
mapping );
|
||||||
}
|
}
|
||||||
@ -1752,13 +1821,16 @@ private void initOrdinaryPropertyPaths(Mapping mapping) throws MappingException
|
|||||||
private void initIdentifierPropertyPaths(Mapping mapping) throws MappingException {
|
private void initIdentifierPropertyPaths(Mapping mapping) throws MappingException {
|
||||||
String idProp = getIdentifierPropertyName();
|
String idProp = getIdentifierPropertyName();
|
||||||
if ( idProp != null ) {
|
if ( idProp != null ) {
|
||||||
propertyMapping.initPropertyPaths( idProp, getIdentifierType(), getIdentifierColumnNames(), null, mapping );
|
propertyMapping.initPropertyPaths( idProp, getIdentifierType(), getIdentifierColumnNames(),
|
||||||
|
getIdentifierColumnReaders(), getIdentifierColumnReaderTemplates(), null, mapping );
|
||||||
}
|
}
|
||||||
if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
|
if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
|
||||||
propertyMapping.initPropertyPaths( null, getIdentifierType(), getIdentifierColumnNames(), null, mapping );
|
propertyMapping.initPropertyPaths( null, getIdentifierType(), getIdentifierColumnNames(),
|
||||||
|
getIdentifierColumnReaders(), getIdentifierColumnReaderTemplates(), null, mapping );
|
||||||
}
|
}
|
||||||
if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
|
if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
|
||||||
propertyMapping.initPropertyPaths( ENTITY_ID, getIdentifierType(), getIdentifierColumnNames(), null, mapping );
|
propertyMapping.initPropertyPaths( ENTITY_ID, getIdentifierType(), getIdentifierColumnNames(),
|
||||||
|
getIdentifierColumnReaders(), getIdentifierColumnReaderTemplates(), null, mapping );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1766,6 +1838,8 @@ private void initDiscriminatorPropertyPath(Mapping mapping) throws MappingExcept
|
|||||||
propertyMapping.initPropertyPaths( ENTITY_CLASS,
|
propertyMapping.initPropertyPaths( ENTITY_CLASS,
|
||||||
getDiscriminatorType(),
|
getDiscriminatorType(),
|
||||||
new String[]{getDiscriminatorColumnName()},
|
new String[]{getDiscriminatorColumnName()},
|
||||||
|
new String[]{getDiscriminatorColumnReaders()},
|
||||||
|
new String[]{getDiscriminatorColumnReaderTemplate()},
|
||||||
new String[]{getDiscriminatorFormulaTemplate()},
|
new String[]{getDiscriminatorFormulaTemplate()},
|
||||||
getFactory() );
|
getFactory() );
|
||||||
}
|
}
|
||||||
@ -1838,17 +1912,17 @@ protected String generateUpdateString(final boolean[] includeProperty,
|
|||||||
|
|
||||||
// select the correct row by either pk or rowid
|
// select the correct row by either pk or rowid
|
||||||
if ( useRowId ) {
|
if ( useRowId ) {
|
||||||
update.setPrimaryKeyColumnNames( new String[]{rowIdName} ); //TODO: eventually, rowIdName[j]
|
update.addPrimaryKeyColumns( new String[]{rowIdName} ); //TODO: eventually, rowIdName[j]
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
update.setPrimaryKeyColumnNames( getKeyColumns( j ) );
|
update.addPrimaryKeyColumns( getKeyColumns( j ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasColumns = false;
|
boolean hasColumns = false;
|
||||||
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
|
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
|
||||||
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
|
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
|
||||||
// this is a property of the table, which we are updating
|
// this is a property of the table, which we are updating
|
||||||
update.addColumns( getPropertyColumnNames(i), propertyColumnUpdateable[i] );
|
update.addColumns( getPropertyColumnNames(i), propertyColumnUpdateable[i], propertyColumnWriters[i] );
|
||||||
hasColumns = hasColumns || getPropertyColumnSpan( i ) > 0;
|
hasColumns = hasColumns || getPropertyColumnSpan( i ) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1879,10 +1953,11 @@ else if ( entityMetamodel.getOptimisticLockMode() > Versioning.OPTIMISTIC_LOCK_V
|
|||||||
// this property belongs to the table, and it is not specifically
|
// this property belongs to the table, and it is not specifically
|
||||||
// excluded from optimistic locking by optimistic-lock="false"
|
// excluded from optimistic locking by optimistic-lock="false"
|
||||||
String[] propertyColumnNames = getPropertyColumnNames( i );
|
String[] propertyColumnNames = getPropertyColumnNames( i );
|
||||||
|
String[] propertyColumnWriters = getPropertyColumnWriters( i );
|
||||||
boolean[] propertyNullness = types[i].toColumnNullness( oldFields[i], getFactory() );
|
boolean[] propertyNullness = types[i].toColumnNullness( oldFields[i], getFactory() );
|
||||||
for ( int k=0; k<propertyNullness.length; k++ ) {
|
for ( int k=0; k<propertyNullness.length; k++ ) {
|
||||||
if ( propertyNullness[k] ) {
|
if ( propertyNullness[k] ) {
|
||||||
update.addWhereColumn( propertyColumnNames[k] );
|
update.addWhereColumn( propertyColumnNames[k], "=" + propertyColumnWriters[k] );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
update.addWhereColumn( propertyColumnNames[k], " is null" );
|
update.addWhereColumn( propertyColumnNames[k], " is null" );
|
||||||
@ -1928,7 +2003,7 @@ protected String generateInsertString(boolean identityInsert, boolean[] includeP
|
|||||||
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
|
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
|
||||||
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
|
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
|
||||||
// this property belongs on the table and is to be inserted
|
// this property belongs on the table and is to be inserted
|
||||||
insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i] );
|
insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i], propertyColumnWriters[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1976,7 +2051,7 @@ protected String generateIdentityInsertString(boolean[] includeProperty) {
|
|||||||
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
|
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
|
||||||
if ( includeProperty[i] && isPropertyOfTable( i, 0 ) ) {
|
if ( includeProperty[i] && isPropertyOfTable( i, 0 ) ) {
|
||||||
// this property belongs on the table and is to be inserted
|
// this property belongs on the table and is to be inserted
|
||||||
insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i] );
|
insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i], propertyColumnWriters[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1998,7 +2073,7 @@ protected String generateIdentityInsertString(boolean[] includeProperty) {
|
|||||||
protected String generateDeleteString(int j) {
|
protected String generateDeleteString(int j) {
|
||||||
Delete delete = new Delete()
|
Delete delete = new Delete()
|
||||||
.setTableName( getTableName( j ) )
|
.setTableName( getTableName( j ) )
|
||||||
.setPrimaryKeyColumnNames( getKeyColumns( j ) );
|
.addPrimaryKeyColumns( getKeyColumns( j ) );
|
||||||
if ( j == 0 ) {
|
if ( j == 0 ) {
|
||||||
delete.setVersionColumnName( getVersionColumnName() );
|
delete.setVersionColumnName( getVersionColumnName() );
|
||||||
}
|
}
|
||||||
@ -2750,7 +2825,7 @@ private String[] generateSQLDeletStrings(Object[] loadedState) {
|
|||||||
for ( int j = span - 1; j >= 0; j-- ) {
|
for ( int j = span - 1; j >= 0; j-- ) {
|
||||||
Delete delete = new Delete()
|
Delete delete = new Delete()
|
||||||
.setTableName( getTableName( j ) )
|
.setTableName( getTableName( j ) )
|
||||||
.setPrimaryKeyColumnNames( getKeyColumns( j ) );
|
.addPrimaryKeyColumns( getKeyColumns( j ) );
|
||||||
if ( getFactory().getSettings().isCommentsEnabled() ) {
|
if ( getFactory().getSettings().isCommentsEnabled() ) {
|
||||||
delete.setComment( "delete " + getEntityName() + " [" + j + "]" );
|
delete.setComment( "delete " + getEntityName() + " [" + j + "]" );
|
||||||
}
|
}
|
||||||
@ -2889,12 +2964,12 @@ protected SelectFragment createSelect(final int[] subclassColumnNumbers,
|
|||||||
|
|
||||||
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
|
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
|
||||||
String[] columnAliases = getSubclassColumnAliasClosure();
|
String[] columnAliases = getSubclassColumnAliasClosure();
|
||||||
String[] columns = getSubclassColumnClosure();
|
String[] columnReaderTemplates = getSubclassColumnReaderTemplateClosure();
|
||||||
for ( int i = 0; i < subclassColumnNumbers.length; i++ ) {
|
for ( int i = 0; i < subclassColumnNumbers.length; i++ ) {
|
||||||
int columnNumber = subclassColumnNumbers[i];
|
int columnNumber = subclassColumnNumbers[i];
|
||||||
if ( subclassColumnSelectableClosure[columnNumber] ) {
|
if ( subclassColumnSelectableClosure[columnNumber] ) {
|
||||||
final String subalias = generateTableAlias( getRootAlias(), columnTableNumbers[columnNumber] );
|
final String subalias = generateTableAlias( getRootAlias(), columnTableNumbers[columnNumber] );
|
||||||
selectFragment.addColumn( subalias, columns[columnNumber], columnAliases[columnNumber] );
|
selectFragment.addColumnTemplate( subalias, columnReaderTemplates[columnNumber], columnAliases[columnNumber] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,12 +47,22 @@ public abstract class AbstractPropertyMapping implements PropertyMapping {
|
|||||||
|
|
||||||
private final Map typesByPropertyPath = new HashMap();
|
private final Map typesByPropertyPath = new HashMap();
|
||||||
private final Map columnsByPropertyPath = new HashMap();
|
private final Map columnsByPropertyPath = new HashMap();
|
||||||
|
private final Map columnReadersByPropertyPath = new HashMap();
|
||||||
|
private final Map columnReaderTemplatesByPropertyPath = new HashMap();
|
||||||
private final Map formulaTemplatesByPropertyPath = new HashMap();
|
private final Map formulaTemplatesByPropertyPath = new HashMap();
|
||||||
|
|
||||||
public String[] getIdentifierColumnNames() {
|
public String[] getIdentifierColumnNames() {
|
||||||
throw new UnsupportedOperationException("one-to-one is not supported here");
|
throw new UnsupportedOperationException("one-to-one is not supported here");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getIdentifierColumnReaderTemplates() {
|
||||||
|
throw new UnsupportedOperationException("one-to-one is not supported here");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getIdentifierColumnReaders() {
|
||||||
|
throw new UnsupportedOperationException("one-to-one is not supported here");
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract String getEntityName();
|
protected abstract String getEntityName();
|
||||||
|
|
||||||
public Type toType(String propertyName) throws QueryException {
|
public Type toType(String propertyName) throws QueryException {
|
||||||
@ -81,14 +91,15 @@ public String[] toColumns(String alias, String propertyName) throws QueryExcepti
|
|||||||
if ( columns == null ) {
|
if ( columns == null ) {
|
||||||
throw propertyException( propertyName );
|
throw propertyException( propertyName );
|
||||||
}
|
}
|
||||||
String[] templates = (String[]) formulaTemplatesByPropertyPath.get(propertyName);
|
String[] formulaTemplates = (String[]) formulaTemplatesByPropertyPath.get(propertyName);
|
||||||
|
String[] columnReaderTemplates = (String[]) columnReaderTemplatesByPropertyPath.get(propertyName);
|
||||||
String[] result = new String[columns.length];
|
String[] result = new String[columns.length];
|
||||||
for ( int i=0; i<columns.length; i++ ) {
|
for ( int i=0; i<columns.length; i++ ) {
|
||||||
if ( columns[i]==null ) {
|
if ( columnReaderTemplates[i]==null ) {
|
||||||
result[i] = StringHelper.replace( templates[i], Template.TEMPLATE, alias );
|
result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE, alias );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result[i] = StringHelper.qualify( alias, columns[i] );
|
result[i] = StringHelper.replace( columnReaderTemplates[i], Template.TEMPLATE, alias );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -99,22 +110,27 @@ public String[] toColumns(String propertyName) throws QueryException {
|
|||||||
if ( columns == null ) {
|
if ( columns == null ) {
|
||||||
throw propertyException( propertyName );
|
throw propertyException( propertyName );
|
||||||
}
|
}
|
||||||
String[] templates = (String[]) formulaTemplatesByPropertyPath.get(propertyName);
|
String[] formulaTemplates = (String[]) formulaTemplatesByPropertyPath.get(propertyName);
|
||||||
|
String[] columnReaders = (String[]) columnReadersByPropertyPath.get(propertyName);
|
||||||
String[] result = new String[columns.length];
|
String[] result = new String[columns.length];
|
||||||
for ( int i=0; i<columns.length; i++ ) {
|
for ( int i=0; i<columns.length; i++ ) {
|
||||||
if ( columns[i]==null ) {
|
if ( columnReaders[i]==null ) {
|
||||||
result[i] = StringHelper.replace( templates[i], Template.TEMPLATE, "" );
|
result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE, "" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result[i] = columns[i];
|
result[i] = columnReaders[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addPropertyPath(String path, Type type, String[] columns, String[] formulaTemplates) {
|
protected void addPropertyPath(String path, Type type, String[] columns,
|
||||||
|
String[] columnReaders, String[] columnReaderTemplates,
|
||||||
|
String[] formulaTemplates) {
|
||||||
typesByPropertyPath.put(path, type);
|
typesByPropertyPath.put(path, type);
|
||||||
columnsByPropertyPath.put(path, columns);
|
columnsByPropertyPath.put(path, columns);
|
||||||
|
columnReadersByPropertyPath.put(path, columnReaders);
|
||||||
|
columnReaderTemplatesByPropertyPath.put(path, columnReaderTemplates);
|
||||||
if (formulaTemplates!=null) {
|
if (formulaTemplates!=null) {
|
||||||
formulaTemplatesByPropertyPath.put(path, formulaTemplates);
|
formulaTemplatesByPropertyPath.put(path, formulaTemplates);
|
||||||
}
|
}
|
||||||
@ -135,6 +151,8 @@ protected void initPropertyPaths(
|
|||||||
final String path,
|
final String path,
|
||||||
final Type type,
|
final Type type,
|
||||||
String[] columns,
|
String[] columns,
|
||||||
|
String[] columnReaders,
|
||||||
|
String[] columnReaderTemplates,
|
||||||
final String[] formulaTemplates,
|
final String[] formulaTemplates,
|
||||||
final Mapping factory)
|
final Mapping factory)
|
||||||
throws MappingException {
|
throws MappingException {
|
||||||
@ -150,6 +168,8 @@ protected void initPropertyPaths(
|
|||||||
AssociationType actype = (AssociationType) type;
|
AssociationType actype = (AssociationType) type;
|
||||||
if ( actype.useLHSPrimaryKey() ) {
|
if ( actype.useLHSPrimaryKey() ) {
|
||||||
columns = getIdentifierColumnNames();
|
columns = getIdentifierColumnNames();
|
||||||
|
columnReaders = getIdentifierColumnReaders();
|
||||||
|
columnReaderTemplates = getIdentifierColumnReaderTemplates();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String foreignKeyProperty = actype.getLHSPropertyName();
|
String foreignKeyProperty = actype.getLHSPropertyName();
|
||||||
@ -158,27 +178,31 @@ protected void initPropertyPaths(
|
|||||||
// referenced property in the mapping file (ok?)
|
// referenced property in the mapping file (ok?)
|
||||||
columns = (String[]) columnsByPropertyPath.get(foreignKeyProperty);
|
columns = (String[]) columnsByPropertyPath.get(foreignKeyProperty);
|
||||||
if (columns==null) return; //get em on the second pass!
|
if (columns==null) return; //get em on the second pass!
|
||||||
|
columnReaders = (String[]) columnReadersByPropertyPath.get(foreignKeyProperty);
|
||||||
|
columnReaderTemplates = (String[]) columnReaderTemplatesByPropertyPath.get(foreignKeyProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path!=null) addPropertyPath(path, type, columns, formulaTemplates);
|
if (path!=null) addPropertyPath(path, type, columns, columnReaders, columnReaderTemplates, formulaTemplates);
|
||||||
|
|
||||||
if ( type.isComponentType() ) {
|
if ( type.isComponentType() ) {
|
||||||
AbstractComponentType actype = (AbstractComponentType) type;
|
AbstractComponentType actype = (AbstractComponentType) type;
|
||||||
initComponentPropertyPaths( path, actype, columns, formulaTemplates, factory );
|
initComponentPropertyPaths( path, actype, columns, columnReaders, columnReaderTemplates, formulaTemplates, factory );
|
||||||
if ( actype.isEmbedded() ) {
|
if ( actype.isEmbedded() ) {
|
||||||
initComponentPropertyPaths(
|
initComponentPropertyPaths(
|
||||||
path==null ? null : StringHelper.qualifier(path),
|
path==null ? null : StringHelper.qualifier(path),
|
||||||
actype,
|
actype,
|
||||||
columns,
|
columns,
|
||||||
|
columnReaders,
|
||||||
|
columnReaderTemplates,
|
||||||
formulaTemplates,
|
formulaTemplates,
|
||||||
factory
|
factory
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( type.isEntityType() ) {
|
else if ( type.isEntityType() ) {
|
||||||
initIdentifierPropertyPaths( path, (EntityType) type, columns, factory );
|
initIdentifierPropertyPaths( path, (EntityType) type, columns, columnReaders, columnReaderTemplates, factory );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,6 +210,8 @@ protected void initIdentifierPropertyPaths(
|
|||||||
final String path,
|
final String path,
|
||||||
final EntityType etype,
|
final EntityType etype,
|
||||||
final String[] columns,
|
final String[] columns,
|
||||||
|
final String[] columnReaders,
|
||||||
|
final String[] columnReaderTemplates,
|
||||||
final Mapping factory) throws MappingException {
|
final Mapping factory) throws MappingException {
|
||||||
|
|
||||||
Type idtype = etype.getIdentifierOrUniqueKeyType( factory );
|
Type idtype = etype.getIdentifierOrUniqueKeyType( factory );
|
||||||
@ -195,15 +221,15 @@ protected void initIdentifierPropertyPaths(
|
|||||||
if ( etype.isReferenceToPrimaryKey() ) {
|
if ( etype.isReferenceToPrimaryKey() ) {
|
||||||
if ( !hasNonIdentifierPropertyNamedId ) {
|
if ( !hasNonIdentifierPropertyNamedId ) {
|
||||||
String idpath1 = extendPath(path, EntityPersister.ENTITY_ID);
|
String idpath1 = extendPath(path, EntityPersister.ENTITY_ID);
|
||||||
addPropertyPath(idpath1, idtype, columns, null);
|
addPropertyPath(idpath1, idtype, columns, columnReaders, columnReaderTemplates, null);
|
||||||
initPropertyPaths(idpath1, idtype, columns, null, factory);
|
initPropertyPaths(idpath1, idtype, columns, columnReaders, columnReaderTemplates, null, factory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idPropName!=null) {
|
if (idPropName!=null) {
|
||||||
String idpath2 = extendPath(path, idPropName);
|
String idpath2 = extendPath(path, idPropName);
|
||||||
addPropertyPath(idpath2, idtype, columns, null);
|
addPropertyPath(idpath2, idtype, columns, columnReaders, columnReaderTemplates, null);
|
||||||
initPropertyPaths(idpath2, idtype, columns, null, factory);
|
initPropertyPaths(idpath2, idtype, columns, columnReaders, columnReaderTemplates, null, factory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +249,8 @@ protected void initComponentPropertyPaths(
|
|||||||
final String path,
|
final String path,
|
||||||
final AbstractComponentType type,
|
final AbstractComponentType type,
|
||||||
final String[] columns,
|
final String[] columns,
|
||||||
|
final String[] columnReaders,
|
||||||
|
final String[] columnReaderTemplates,
|
||||||
String[] formulaTemplates, final Mapping factory)
|
String[] formulaTemplates, final Mapping factory)
|
||||||
throws MappingException {
|
throws MappingException {
|
||||||
|
|
||||||
@ -234,9 +262,11 @@ protected void initComponentPropertyPaths(
|
|||||||
try {
|
try {
|
||||||
int length = types[i].getColumnSpan(factory);
|
int length = types[i].getColumnSpan(factory);
|
||||||
String[] columnSlice = ArrayHelper.slice(columns, begin, length);
|
String[] columnSlice = ArrayHelper.slice(columns, begin, length);
|
||||||
|
String[] columnReaderSlice = ArrayHelper.slice(columnReaders, begin, length);
|
||||||
|
String[] columnReaderTemplateSlice = ArrayHelper.slice(columnReaderTemplates, begin, length);
|
||||||
String[] formulaSlice = formulaTemplates==null ?
|
String[] formulaSlice = formulaTemplates==null ?
|
||||||
null : ArrayHelper.slice(formulaTemplates, begin, length);
|
null : ArrayHelper.slice(formulaTemplates, begin, length);
|
||||||
initPropertyPaths(subpath, types[i], columnSlice, formulaSlice, factory);
|
initPropertyPaths(subpath, types[i], columnSlice, columnReaderSlice, columnReaderTemplateSlice, formulaSlice, factory);
|
||||||
begin+=length;
|
begin+=length;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
@ -41,6 +41,14 @@ public BasicEntityPropertyMapping(AbstractEntityPersister persister) {
|
|||||||
public String[] getIdentifierColumnNames() {
|
public String[] getIdentifierColumnNames() {
|
||||||
return persister.getIdentifierColumnNames();
|
return persister.getIdentifierColumnNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getIdentifierColumnReaders() {
|
||||||
|
return persister.getIdentifierColumnReaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getIdentifierColumnReaderTemplates() {
|
||||||
|
return persister.getIdentifierColumnReaderTemplates();
|
||||||
|
}
|
||||||
|
|
||||||
protected String getEntityName() {
|
protected String getEntityName() {
|
||||||
return persister.getEntityName();
|
return persister.getEntityName();
|
||||||
|
@ -36,10 +36,10 @@
|
|||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
||||||
|
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
||||||
import org.hibernate.engine.Mapping;
|
import org.hibernate.engine.Mapping;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.Versioning;
|
import org.hibernate.engine.Versioning;
|
||||||
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
import org.hibernate.mapping.KeyValue;
|
import org.hibernate.mapping.KeyValue;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
@ -65,7 +65,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||||||
private final String[] tableNames;
|
private final String[] tableNames;
|
||||||
private final String[] naturalOrderTableNames;
|
private final String[] naturalOrderTableNames;
|
||||||
private final String[][] tableKeyColumns;
|
private final String[][] tableKeyColumns;
|
||||||
|
private final String[][] tableKeyColumnReaders;
|
||||||
|
private final String[][] tableKeyColumnReaderTemplates;
|
||||||
private final String[][] naturalOrderTableKeyColumns;
|
private final String[][] naturalOrderTableKeyColumns;
|
||||||
|
private final String[][] naturalOrderTableKeyColumnReaders;
|
||||||
|
private final String[][] naturalOrderTableKeyColumnReaderTemplates;
|
||||||
private final boolean[] naturalOrderCascadeDeleteEnabled;
|
private final boolean[] naturalOrderCascadeDeleteEnabled;
|
||||||
|
|
||||||
private final String[] spaces;
|
private final String[] spaces;
|
||||||
@ -139,6 +143,8 @@ public JoinedSubclassEntityPersister(
|
|||||||
|
|
||||||
ArrayList tables = new ArrayList();
|
ArrayList tables = new ArrayList();
|
||||||
ArrayList keyColumns = new ArrayList();
|
ArrayList keyColumns = new ArrayList();
|
||||||
|
ArrayList keyColumnReaders = new ArrayList();
|
||||||
|
ArrayList keyColumnReaderTemplates = new ArrayList();
|
||||||
ArrayList cascadeDeletes = new ArrayList();
|
ArrayList cascadeDeletes = new ArrayList();
|
||||||
Iterator titer = persistentClass.getTableClosureIterator();
|
Iterator titer = persistentClass.getTableClosureIterator();
|
||||||
Iterator kiter = persistentClass.getKeyClosureIterator();
|
Iterator kiter = persistentClass.getKeyClosureIterator();
|
||||||
@ -152,15 +158,24 @@ public JoinedSubclassEntityPersister(
|
|||||||
);
|
);
|
||||||
tables.add(tabname);
|
tables.add(tabname);
|
||||||
String[] keyCols = new String[idColumnSpan];
|
String[] keyCols = new String[idColumnSpan];
|
||||||
|
String[] keyColReaders = new String[idColumnSpan];
|
||||||
|
String[] keyColReaderTemplates = new String[idColumnSpan];
|
||||||
Iterator citer = key.getColumnIterator();
|
Iterator citer = key.getColumnIterator();
|
||||||
for ( int k=0; k<idColumnSpan; k++ ) {
|
for ( int k=0; k<idColumnSpan; k++ ) {
|
||||||
keyCols[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() );
|
Column column = (Column) citer.next();
|
||||||
|
keyCols[k] = column.getQuotedName( factory.getDialect() );
|
||||||
|
keyColReaders[k] = column.getReadExpr( factory.getDialect() );
|
||||||
|
keyColReaderTemplates[k] = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||||
}
|
}
|
||||||
keyColumns.add(keyCols);
|
keyColumns.add(keyCols);
|
||||||
|
keyColumnReaders.add(keyColReaders);
|
||||||
|
keyColumnReaderTemplates.add(keyColReaderTemplates);
|
||||||
cascadeDeletes.add( new Boolean( key.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete() ) );
|
cascadeDeletes.add( new Boolean( key.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete() ) );
|
||||||
}
|
}
|
||||||
naturalOrderTableNames = ArrayHelper.toStringArray(tables);
|
naturalOrderTableNames = ArrayHelper.toStringArray(tables);
|
||||||
naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray(keyColumns);
|
naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray(keyColumns);
|
||||||
|
naturalOrderTableKeyColumnReaders = ArrayHelper.to2DStringArray(keyColumnReaders);
|
||||||
|
naturalOrderTableKeyColumnReaderTemplates = ArrayHelper.to2DStringArray(keyColumnReaderTemplates);
|
||||||
naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray(cascadeDeletes);
|
naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray(cascadeDeletes);
|
||||||
|
|
||||||
ArrayList subtables = new ArrayList();
|
ArrayList subtables = new ArrayList();
|
||||||
@ -198,6 +213,8 @@ public JoinedSubclassEntityPersister(
|
|||||||
tableSpan = naturalOrderTableNames.length;
|
tableSpan = naturalOrderTableNames.length;
|
||||||
tableNames = reverse(naturalOrderTableNames);
|
tableNames = reverse(naturalOrderTableNames);
|
||||||
tableKeyColumns = reverse(naturalOrderTableKeyColumns);
|
tableKeyColumns = reverse(naturalOrderTableKeyColumns);
|
||||||
|
tableKeyColumnReaders = reverse(naturalOrderTableKeyColumnReaders);
|
||||||
|
tableKeyColumnReaderTemplates = reverse(naturalOrderTableKeyColumnReaderTemplates);
|
||||||
reverse(subclassTableNameClosure, tableSpan);
|
reverse(subclassTableNameClosure, tableSpan);
|
||||||
reverse(subclassTableKeyColumnClosure, tableSpan);
|
reverse(subclassTableKeyColumnClosure, tableSpan);
|
||||||
|
|
||||||
@ -514,6 +531,14 @@ public String[] getIdentifierColumnNames() {
|
|||||||
return tableKeyColumns[0];
|
return tableKeyColumns[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getIdentifierColumnReaderTemplates() {
|
||||||
|
return tableKeyColumnReaderTemplates[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getIdentifierColumnReaders() {
|
||||||
|
return tableKeyColumnReaders[0];
|
||||||
|
}
|
||||||
|
|
||||||
public String[] toColumns(String alias, String propertyName) throws QueryException {
|
public String[] toColumns(String alias, String propertyName) throws QueryException {
|
||||||
|
|
||||||
if ( ENTITY_CLASS.equals(propertyName) ) {
|
if ( ENTITY_CLASS.equals(propertyName) ) {
|
||||||
|
@ -35,9 +35,9 @@
|
|||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.access.EntityRegionAccessStrategy;
|
||||||
|
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
||||||
import org.hibernate.engine.Mapping;
|
import org.hibernate.engine.Mapping;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
|
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
import org.hibernate.mapping.Formula;
|
import org.hibernate.mapping.Formula;
|
||||||
import org.hibernate.mapping.Join;
|
import org.hibernate.mapping.Join;
|
||||||
@ -102,6 +102,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||||||
private final Map subclassesByDiscriminatorValue = new HashMap();
|
private final Map subclassesByDiscriminatorValue = new HashMap();
|
||||||
private final boolean forceDiscriminator;
|
private final boolean forceDiscriminator;
|
||||||
private final String discriminatorColumnName;
|
private final String discriminatorColumnName;
|
||||||
|
private final String discriminatorColumnReaders;
|
||||||
|
private final String discriminatorColumnReaderTemplate;
|
||||||
private final String discriminatorFormula;
|
private final String discriminatorFormula;
|
||||||
private final String discriminatorFormulaTemplate;
|
private final String discriminatorFormulaTemplate;
|
||||||
private final String discriminatorAlias;
|
private final String discriminatorAlias;
|
||||||
@ -295,11 +297,15 @@ public SingleTableEntityPersister(
|
|||||||
discriminatorFormula = formula.getFormula();
|
discriminatorFormula = formula.getFormula();
|
||||||
discriminatorFormulaTemplate = formula.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
discriminatorFormulaTemplate = formula.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||||
discriminatorColumnName = null;
|
discriminatorColumnName = null;
|
||||||
|
discriminatorColumnReaders = null;
|
||||||
|
discriminatorColumnReaderTemplate = null;
|
||||||
discriminatorAlias = "clazz_";
|
discriminatorAlias = "clazz_";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Column column = (Column) selectable;
|
Column column = (Column) selectable;
|
||||||
discriminatorColumnName = column.getQuotedName( factory.getDialect() );
|
discriminatorColumnName = column.getQuotedName( factory.getDialect() );
|
||||||
|
discriminatorColumnReaders = column.getReadExpr( factory.getDialect() );
|
||||||
|
discriminatorColumnReaderTemplate = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||||
discriminatorAlias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() );
|
discriminatorAlias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() );
|
||||||
discriminatorFormula = null;
|
discriminatorFormula = null;
|
||||||
discriminatorFormulaTemplate = null;
|
discriminatorFormulaTemplate = null;
|
||||||
@ -334,6 +340,8 @@ else if ( persistentClass.isDiscriminatorValueNotNull() ) {
|
|||||||
forceDiscriminator = false;
|
forceDiscriminator = false;
|
||||||
discriminatorInsertable = false;
|
discriminatorInsertable = false;
|
||||||
discriminatorColumnName = null;
|
discriminatorColumnName = null;
|
||||||
|
discriminatorColumnReaders = null;
|
||||||
|
discriminatorColumnReaderTemplate = null;
|
||||||
discriminatorAlias = null;
|
discriminatorAlias = null;
|
||||||
discriminatorType = null;
|
discriminatorType = null;
|
||||||
discriminatorValue = null;
|
discriminatorValue = null;
|
||||||
@ -444,6 +452,14 @@ public String getDiscriminatorColumnName() {
|
|||||||
return discriminatorColumnName;
|
return discriminatorColumnName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDiscriminatorColumnReaders() {
|
||||||
|
return discriminatorColumnReaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDiscriminatorColumnReaderTemplate() {
|
||||||
|
return discriminatorColumnReaderTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getDiscriminatorAlias() {
|
protected String getDiscriminatorAlias() {
|
||||||
return discriminatorAlias;
|
return discriminatorAlias;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.hibernate.sql;
|
package org.hibernate.sql;
|
||||||
|
|
||||||
import org.hibernate.util.StringHelper;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.cglib.transform.impl.AddPropertyTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An SQL <tt>DELETE</tt> statement
|
* An SQL <tt>DELETE</tt> statement
|
||||||
@ -34,10 +38,11 @@
|
|||||||
public class Delete {
|
public class Delete {
|
||||||
|
|
||||||
private String tableName;
|
private String tableName;
|
||||||
private String[] primaryKeyColumnNames;
|
|
||||||
private String versionColumnName;
|
private String versionColumnName;
|
||||||
private String where;
|
private String where;
|
||||||
|
|
||||||
|
private Map primaryKeyColumns = new LinkedHashMap();
|
||||||
|
|
||||||
private String comment;
|
private String comment;
|
||||||
public Delete setComment(String comment) {
|
public Delete setComment(String comment) {
|
||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
@ -55,12 +60,17 @@ public String toStatementString() {
|
|||||||
buf.append( "/* " ).append(comment).append( " */ " );
|
buf.append( "/* " ).append(comment).append( " */ " );
|
||||||
}
|
}
|
||||||
buf.append( "delete from " ).append(tableName);
|
buf.append( "delete from " ).append(tableName);
|
||||||
if ( where != null || primaryKeyColumnNames != null || versionColumnName != null ) {
|
if ( where != null || !primaryKeyColumns.isEmpty() || versionColumnName != null ) {
|
||||||
buf.append( " where " );
|
buf.append( " where " );
|
||||||
}
|
}
|
||||||
boolean conditionsAppended = false;
|
boolean conditionsAppended = false;
|
||||||
if ( primaryKeyColumnNames != null ) {
|
Iterator iter = primaryKeyColumns.entrySet().iterator();
|
||||||
buf.append( StringHelper.join( "=? and ", primaryKeyColumnNames ) ).append( "=?" );
|
while ( iter.hasNext() ) {
|
||||||
|
Map.Entry e = (Map.Entry) iter.next();
|
||||||
|
buf.append( e.getKey() ).append( '=' ).append( e.getValue() );
|
||||||
|
if ( iter.hasNext() ) {
|
||||||
|
buf.append( " and " );
|
||||||
|
}
|
||||||
conditionsAppended = true;
|
conditionsAppended = true;
|
||||||
}
|
}
|
||||||
if ( where!=null ) {
|
if ( where!=null ) {
|
||||||
@ -94,8 +104,35 @@ public Delete addWhereFragment(String fragment) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Delete setPrimaryKeyColumnNames(String[] primaryKeyColumnNames) {
|
public Delete setPrimaryKeyColumnNames(String[] columnNames) {
|
||||||
this.primaryKeyColumnNames = primaryKeyColumnNames;
|
this.primaryKeyColumns.clear();
|
||||||
|
addPrimaryKeyColumns(columnNames);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Delete addPrimaryKeyColumns(String[] columnNames) {
|
||||||
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
|
addPrimaryKeyColumn( columnNames[i], "?" );
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Delete addPrimaryKeyColumns(String[] columnNames, boolean[] includeColumns, String[] valueExpressions) {
|
||||||
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
|
if( includeColumns[i] ) addPrimaryKeyColumn( columnNames[i], valueExpressions[i] );
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Delete addPrimaryKeyColumns(String[] columnNames, String[] valueExpressions) {
|
||||||
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
|
addPrimaryKeyColumn( columnNames[i], valueExpressions[i] );
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Delete addPrimaryKeyColumn(String columnName, String valueExpression) {
|
||||||
|
this.primaryKeyColumns.put(columnName, valueExpression);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
package org.hibernate.sql;
|
package org.hibernate.sql;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.type.LiteralType;
|
import org.hibernate.type.LiteralType;
|
||||||
@ -75,8 +75,17 @@ public Insert addColumns(String[] columnNames, boolean[] insertable) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Insert addColumn(String columnName, String value) {
|
public Insert addColumns(String[] columnNames, boolean[] insertable, String[] valueExpressions) {
|
||||||
columns.put(columnName, value);
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
|
if ( insertable[i] ) {
|
||||||
|
addColumn( columnNames[i], valueExpressions[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Insert addColumn(String columnName, String valueExpression) {
|
||||||
|
columns.put(columnName, valueExpression);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,17 @@ public SelectFragment addFormula(String tableAlias, String formula, String formu
|
|||||||
columnAliases.add(formulaAlias);
|
columnAliases.add(formulaAlias);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SelectFragment addColumnTemplate(String tableAlias, String columnTemplate, String columnAlias) {
|
||||||
|
// In this context, there's no difference between a column template and a formula.
|
||||||
|
return addFormula( tableAlias, columnTemplate, columnAlias );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectFragment addColumnTemplates(String tableAlias, String[] columnTemplates, String columnAliases[]) {
|
||||||
|
// In this context, there's no difference between a column template and a formula.
|
||||||
|
return addFormulas( tableAlias, columnTemplates, columnAliases );
|
||||||
|
}
|
||||||
|
|
||||||
public String toFragmentString() {
|
public String toFragmentString() {
|
||||||
StringBuffer buf = new StringBuffer( columns.size() * 10 );
|
StringBuffer buf = new StringBuffer( columns.size() * 10 );
|
||||||
Iterator iter = columns.iterator();
|
Iterator iter = columns.iterator();
|
||||||
|
@ -25,12 +25,11 @@
|
|||||||
package org.hibernate.sql;
|
package org.hibernate.sql;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.type.LiteralType;
|
import org.hibernate.type.LiteralType;
|
||||||
import org.hibernate.util.StringHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An SQL <tt>UPDATE</tt> statement
|
* An SQL <tt>UPDATE</tt> statement
|
||||||
@ -40,12 +39,12 @@
|
|||||||
public class Update {
|
public class Update {
|
||||||
|
|
||||||
private String tableName;
|
private String tableName;
|
||||||
private String[] primaryKeyColumnNames;
|
|
||||||
private String versionColumnName;
|
private String versionColumnName;
|
||||||
private String where;
|
private String where;
|
||||||
private String assignments;
|
private String assignments;
|
||||||
private String comment;
|
private String comment;
|
||||||
|
|
||||||
|
private Map primaryKeyColumns = new LinkedHashMap();
|
||||||
private Map columns = new LinkedHashMap();
|
private Map columns = new LinkedHashMap();
|
||||||
private Map whereColumns = new LinkedHashMap();
|
private Map whereColumns = new LinkedHashMap();
|
||||||
|
|
||||||
@ -74,11 +73,38 @@ public Update setTableName(String tableName) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Update setPrimaryKeyColumnNames(String[] primaryKeyColumnNames) {
|
public Update setPrimaryKeyColumnNames(String[] columnNames) {
|
||||||
this.primaryKeyColumnNames = primaryKeyColumnNames;
|
this.primaryKeyColumns.clear();
|
||||||
|
addPrimaryKeyColumns(columnNames);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Update addPrimaryKeyColumns(String[] columnNames) {
|
||||||
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
|
addPrimaryKeyColumn( columnNames[i], "?" );
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Update addPrimaryKeyColumns(String[] columnNames, boolean[] includeColumns, String[] valueExpressions) {
|
||||||
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
|
if( includeColumns[i] ) addPrimaryKeyColumn( columnNames[i], valueExpressions[i] );
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Update addPrimaryKeyColumns(String[] columnNames, String[] valueExpressions) {
|
||||||
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
|
addPrimaryKeyColumn( columnNames[i], valueExpressions[i] );
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Update addPrimaryKeyColumn(String columnName, String valueExpression) {
|
||||||
|
this.primaryKeyColumns.put(columnName, valueExpression);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Update setVersionColumnName(String versionColumnName) {
|
public Update setVersionColumnName(String versionColumnName) {
|
||||||
this.versionColumnName = versionColumnName;
|
this.versionColumnName = versionColumnName;
|
||||||
return this;
|
return this;
|
||||||
@ -89,7 +115,7 @@ public Update setComment(String comment) {
|
|||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Update addColumns(String[] columnNames) {
|
public Update addColumns(String[] columnNames) {
|
||||||
for ( int i=0; i<columnNames.length; i++ ) {
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
addColumn( columnNames[i] );
|
addColumn( columnNames[i] );
|
||||||
@ -97,16 +123,16 @@ public Update addColumns(String[] columnNames) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Update addColumns(String[] columnNames, boolean[] updateable) {
|
public Update addColumns(String[] columnNames, boolean[] updateable, String[] valueExpressions) {
|
||||||
for ( int i=0; i<columnNames.length; i++ ) {
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
if ( updateable[i] ) addColumn( columnNames[i] );
|
if ( updateable[i] ) addColumn( columnNames[i], valueExpressions[i] );
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Update addColumns(String[] columnNames, String value) {
|
public Update addColumns(String[] columnNames, String valueExpression) {
|
||||||
for ( int i=0; i<columnNames.length; i++ ) {
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
addColumn( columnNames[i], value );
|
addColumn( columnNames[i], valueExpression );
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -115,8 +141,8 @@ public Update addColumn(String columnName) {
|
|||||||
return addColumn(columnName, "?");
|
return addColumn(columnName, "?");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Update addColumn(String columnName, String value) {
|
public Update addColumn(String columnName, String valueExpression) {
|
||||||
columns.put(columnName, value);
|
columns.put(columnName, valueExpression);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,9 +157,9 @@ public Update addWhereColumns(String[] columnNames) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Update addWhereColumns(String[] columnNames, String value) {
|
public Update addWhereColumns(String[] columnNames, String valueExpression) {
|
||||||
for ( int i=0; i<columnNames.length; i++ ) {
|
for ( int i=0; i<columnNames.length; i++ ) {
|
||||||
addWhereColumn( columnNames[i], value );
|
addWhereColumn( columnNames[i], valueExpression );
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -142,8 +168,8 @@ public Update addWhereColumn(String columnName) {
|
|||||||
return addWhereColumn(columnName, "=?");
|
return addWhereColumn(columnName, "=?");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Update addWhereColumn(String columnName, String value) {
|
public Update addWhereColumn(String columnName, String valueExpression) {
|
||||||
whereColumns.put(columnName, value);
|
whereColumns.put(columnName, valueExpression);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,11 +202,16 @@ public String toStatementString() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean conditionsAppended = false;
|
boolean conditionsAppended = false;
|
||||||
if ( primaryKeyColumnNames != null || where != null || !whereColumns.isEmpty() || versionColumnName != null ) {
|
if ( !primaryKeyColumns.isEmpty() || where != null || !whereColumns.isEmpty() || versionColumnName != null ) {
|
||||||
buf.append( " where " );
|
buf.append( " where " );
|
||||||
}
|
}
|
||||||
if ( primaryKeyColumnNames != null ) {
|
iter = primaryKeyColumns.entrySet().iterator();
|
||||||
buf.append( StringHelper.join( "=? and ", primaryKeyColumnNames ) ).append( "=?" );
|
while ( iter.hasNext() ) {
|
||||||
|
Map.Entry e = (Map.Entry) iter.next();
|
||||||
|
buf.append( e.getKey() ).append( '=' ).append( e.getValue() );
|
||||||
|
if ( iter.hasNext() ) {
|
||||||
|
buf.append( " and " );
|
||||||
|
}
|
||||||
conditionsAppended = true;
|
conditionsAppended = true;
|
||||||
}
|
}
|
||||||
if ( where != null ) {
|
if ( where != null ) {
|
||||||
|
@ -916,6 +916,8 @@ mapping associations to classes with composite ids. -->
|
|||||||
<!ATTLIST column index CDATA #IMPLIED>
|
<!ATTLIST column index CDATA #IMPLIED>
|
||||||
<!ATTLIST column check CDATA #IMPLIED> <!-- default: no check constraint -->
|
<!ATTLIST column check CDATA #IMPLIED> <!-- default: no check constraint -->
|
||||||
<!ATTLIST column default CDATA #IMPLIED> <!-- default: no default value -->
|
<!ATTLIST column default CDATA #IMPLIED> <!-- default: no default value -->
|
||||||
|
<!ATTLIST column read CDATA #IMPLIED> <!-- default: column name -->
|
||||||
|
<!ATTLIST column write CDATA #IMPLIED> <!-- default: parameter placeholder ('?') -->
|
||||||
|
|
||||||
<!-- The formula and subselect elements allow us to map derived properties and
|
<!-- The formula and subselect elements allow us to map derived properties and
|
||||||
entities. -->
|
entities. -->
|
||||||
|
@ -2788,7 +2788,7 @@
|
|||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="mapping-column" revision="4">
|
<sect2 id="mapping-column" revision="5">
|
||||||
<title>Column and formula elements</title>
|
<title>Column and formula elements</title>
|
||||||
<para>
|
<para>
|
||||||
Mapping elements which accept a <literal>column</literal> attribute will alternatively
|
Mapping elements which accept a <literal>column</literal> attribute will alternatively
|
||||||
@ -2807,12 +2807,22 @@
|
|||||||
index="index_name"
|
index="index_name"
|
||||||
sql-type="sql_type_name"
|
sql-type="sql_type_name"
|
||||||
check="SQL expression"
|
check="SQL expression"
|
||||||
default="SQL expression"/>]]></programlisting>
|
default="SQL expression"
|
||||||
|
read="SQL expression"
|
||||||
|
write="SQL expression"/>]]></programlisting>
|
||||||
|
|
||||||
<programlisting><![CDATA[<formula>SQL expression</formula>]]></programlisting>
|
<programlisting><![CDATA[<formula>SQL expression</formula>]]></programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<literal>column</literal> and <literal>formula</literal> attributes can even be combined
|
Most of the attributes on <literal>column</literal> provide a means of tailoring the
|
||||||
|
DDL during automatic schema generation. The <literal>read</literal> and <literal>write</literal>
|
||||||
|
attributes allow you to specify custom SQL that Hibernate will use to access the column's value.
|
||||||
|
For more on this, see the discussion of
|
||||||
|
<link linkend="mapping-column-read-and-write">column read and write expressions</link>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The <literal>column</literal> and <literal>formula</literal> elements can even be combined
|
||||||
within the same property or association mapping to express, for example, exotic join
|
within the same property or association mapping to express, for example, exotic join
|
||||||
conditions.
|
conditions.
|
||||||
</para>
|
</para>
|
||||||
@ -3544,6 +3554,44 @@ public class Customer implements Serializable {
|
|||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="mapping-column-read-and-write" revision="1">
|
||||||
|
<title>Column read and write expressions</title>
|
||||||
|
<para>
|
||||||
|
Hibernate allows you to customize the SQL it uses to read and write the values
|
||||||
|
of columns mapped to <link linkend="mapping-declaration-property">simple properties</link>.
|
||||||
|
For example, if your database provides a set of data encryption functions, you can
|
||||||
|
invoke them for individual columns like this:
|
||||||
|
<programlisting><![CDATA[<property name="creditCardNumber">
|
||||||
|
<column
|
||||||
|
name="credit_card_num"
|
||||||
|
read="decrypt(credit_card_num)"
|
||||||
|
write="encrypt(?)"/>
|
||||||
|
</property>]]></programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Hibernate applies the custom expressions automatically whenever the property is
|
||||||
|
referenced in a query. This functionality is similar to a derived-property
|
||||||
|
<literal>formula</literal> with two differences:
|
||||||
|
<itemizedlist spacing="compact">
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The property is backed by one or more columns that are exported as part of automatic
|
||||||
|
schema generation.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The property is read-write, not read-only.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>write</literal> expression, if specified, must contain exactly one '?' placeholder
|
||||||
|
for the value.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="mapping-database-object">
|
<sect1 id="mapping-database-object">
|
||||||
<title>Auxiliary database objects</title>
|
<title>Auxiliary database objects</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -662,10 +662,15 @@ BEGIN
|
|||||||
<sect1 id="querysql-cud">
|
<sect1 id="querysql-cud">
|
||||||
<title>Custom SQL for create, update and delete</title>
|
<title>Custom SQL for create, update and delete</title>
|
||||||
|
|
||||||
<para>Hibernate3 can use custom SQL statements for create, update, and
|
<para>Hibernate3 can use custom SQL for create, update, and delete operations.
|
||||||
delete operations. The class and collection persisters in Hibernate
|
The SQL can be overridden at the statement level or inidividual column level. This
|
||||||
already contain a set of configuration time generated strings (insertsql,
|
section describes statement overrides. For columns, see
|
||||||
deletesql, updatesql etc.). The mapping tags
|
<xref linkend="mapping-column-read-and-write"/>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The class and collection persisters in Hibernate already contain a set of
|
||||||
|
configuration time generated strings (insertsql, deletesql, updatesql etc.).
|
||||||
|
The mapping tags
|
||||||
<literal><sql-insert></literal>,
|
<literal><sql-insert></literal>,
|
||||||
<literal><sql-delete></literal>, and
|
<literal><sql-delete></literal>, and
|
||||||
<literal><sql-update></literal> override these strings:</para>
|
<literal><sql-update></literal> override these strings:</para>
|
||||||
@ -732,7 +737,11 @@ END updatePerson;]]></programlisting>
|
|||||||
<title>Custom SQL for loading</title>
|
<title>Custom SQL for loading</title>
|
||||||
|
|
||||||
<para>You can also declare your own SQL (or HQL) queries for entity
|
<para>You can also declare your own SQL (or HQL) queries for entity
|
||||||
loading:</para>
|
loading. As with inserts, updates, and deletes, this can be done at the
|
||||||
|
individual column level as described in
|
||||||
|
<xref linkend="mapping-column-read-and-write"/>
|
||||||
|
or at the statement level. Here is an example of a statement level override:
|
||||||
|
</para>
|
||||||
|
|
||||||
<programlisting><![CDATA[<sql-query name="person">
|
<programlisting><![CDATA[<sql-query name="person">
|
||||||
<return alias="pers" class="Person" lock-mode="upgrade"/>
|
<return alias="pers" class="Person" lock-mode="upgrade"/>
|
||||||
|
@ -7,16 +7,17 @@
|
|||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.Hibernate;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.cfg.Mappings;
|
import org.hibernate.cfg.Mappings;
|
||||||
import org.hibernate.criterion.Property;
|
import org.hibernate.criterion.Property;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
|
||||||
import org.hibernate.dialect.SybaseASE15Dialect;
|
import org.hibernate.dialect.SybaseASE15Dialect;
|
||||||
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
import org.hibernate.mapping.Component;
|
import org.hibernate.mapping.Component;
|
||||||
@ -207,6 +208,48 @@ public void testComponentFormulaQuery() {
|
|||||||
t.commit();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
User u = new User( "steve", "hibernater", new Person( "Steve Ebersole", new Date(), "Main St") );
|
||||||
|
final double HEIGHT_INCHES = 73;
|
||||||
|
final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d;
|
||||||
|
u.getPerson().setHeightInches(HEIGHT_INCHES);
|
||||||
|
s.persist( u );
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Test value conversion during insert
|
||||||
|
Double heightViaSql = (Double)s.createSQLQuery("select height_centimeters from t_user where t_user.username='steve'").uniqueResult();
|
||||||
|
assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
|
||||||
|
|
||||||
|
// Test projection
|
||||||
|
Double heightViaHql = (Double)s.createQuery("select u.person.heightInches from User u where u.id = 'steve'").uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, heightViaHql, 0.01d);
|
||||||
|
|
||||||
|
// Test restriction and entity load via criteria
|
||||||
|
u = (User)s.createCriteria(User.class)
|
||||||
|
.add(Restrictions.between("person.heightInches", HEIGHT_INCHES - 0.01d, HEIGHT_INCHES + 0.01d))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, u.getPerson().getHeightInches(), 0.01d);
|
||||||
|
|
||||||
|
// Test predicate and entity load via HQL
|
||||||
|
u = (User)s.createQuery("from User u where u.person.heightInches between ? and ?")
|
||||||
|
.setDouble(0, HEIGHT_INCHES - 0.01d)
|
||||||
|
.setDouble(1, HEIGHT_INCHES + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, u.getPerson().getHeightInches(), 0.01d);
|
||||||
|
|
||||||
|
// Test update
|
||||||
|
u.getPerson().setHeightInches(1);
|
||||||
|
s.flush();
|
||||||
|
heightViaSql = (Double)s.createSQLQuery("select height_centimeters from t_user where t_user.username='steve'").uniqueResult();
|
||||||
|
assertEquals(2.54d, heightViaSql, 0.01d);
|
||||||
|
s.delete(u);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testNamedQuery() {
|
public void testNamedQuery() {
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
|
@ -13,6 +13,7 @@ public class Person {
|
|||||||
private String currentAddress;
|
private String currentAddress;
|
||||||
private String previousAddress;
|
private String previousAddress;
|
||||||
private int yob;
|
private int yob;
|
||||||
|
private double heightInches;
|
||||||
Person() {}
|
Person() {}
|
||||||
public Person(String name, Date dob, String address) {
|
public Person(String name, Date dob, String address) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -60,4 +61,10 @@ public String getCurrentAddress() {
|
|||||||
public void setCurrentAddress(String currentAddress) {
|
public void setCurrentAddress(String currentAddress) {
|
||||||
this.currentAddress = currentAddress;
|
this.currentAddress = currentAddress;
|
||||||
}
|
}
|
||||||
|
public double getHeightInches() {
|
||||||
|
return heightInches;
|
||||||
|
}
|
||||||
|
public void setHeightInches(double heightInches) {
|
||||||
|
this.heightInches = heightInches;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,12 @@
|
|||||||
<property name="address"/>
|
<property name="address"/>
|
||||||
<property name="previousAddress" insert="false"/>
|
<property name="previousAddress" insert="false"/>
|
||||||
<property name="yob" formula="year(dob)"/>
|
<property name="yob" formula="year(dob)"/>
|
||||||
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"
|
||||||
|
write="? * 2.54"/>
|
||||||
|
</property>
|
||||||
<property name="currentAddress"
|
<property name="currentAddress"
|
||||||
column="address"
|
column="address"
|
||||||
insert="false"
|
insert="false"
|
||||||
|
@ -9,6 +9,7 @@ public class Child {
|
|||||||
private String bio;
|
private String bio;
|
||||||
private Parent parent;
|
private Parent parent;
|
||||||
private int bioLength;
|
private int bioLength;
|
||||||
|
private double heightInches;
|
||||||
Child() {}
|
Child() {}
|
||||||
public Child(String name) {
|
public Child(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -43,6 +44,12 @@ public String getBio() {
|
|||||||
public void setBio(String bio) {
|
public void setBio(String bio) {
|
||||||
this.bio = bio;
|
this.bio = bio;
|
||||||
}
|
}
|
||||||
|
public double getHeightInches() {
|
||||||
|
return heightInches;
|
||||||
|
}
|
||||||
|
public void setHeightInches(double heightInches) {
|
||||||
|
this.heightInches = heightInches;
|
||||||
|
}
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return name.hashCode();
|
return name.hashCode();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.cfg.Mappings;
|
import org.hibernate.cfg.Mappings;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
@ -85,6 +86,52 @@ public void testHandSQL() {
|
|||||||
t.commit();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
final double HEIGHT_INCHES = 49;
|
||||||
|
final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d;
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
Child c = new Child( "Child One" );
|
||||||
|
c.setHeightInches(HEIGHT_INCHES);
|
||||||
|
Parent p = new Parent( "Parent" );
|
||||||
|
p.getChildren().add( c );
|
||||||
|
c.setParent( p );
|
||||||
|
s.save( p );
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Test value conversion during insert
|
||||||
|
Double heightViaSql = (Double)s.createSQLQuery("select height_centimeters from parentchild c where c.name='Child One'")
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
|
||||||
|
|
||||||
|
// Test projection
|
||||||
|
Double heightViaHql = (Double)s.createQuery("select c.heightInches from Parent p join p.children c where p.name='Parent'")
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, heightViaHql, 0.01d);
|
||||||
|
|
||||||
|
// Test entity load via criteria
|
||||||
|
p = (Parent)s.createCriteria(Parent.class).add(Restrictions.eq("name", "Parent")).uniqueResult();
|
||||||
|
c = (Child)p.getChildren().iterator().next();
|
||||||
|
assertEquals(HEIGHT_INCHES, c.getHeightInches(), 0.01d);
|
||||||
|
|
||||||
|
// Test predicate and entity load via HQL
|
||||||
|
p = (Parent)s.createQuery("from Parent p join p.children c where c.heightInches between ? and ?")
|
||||||
|
.setDouble(0, HEIGHT_INCHES - 0.01d)
|
||||||
|
.setDouble(1, HEIGHT_INCHES + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
c = (Child)p.getChildren().iterator().next();
|
||||||
|
assertEquals(HEIGHT_INCHES, c.getHeightInches(), 0.01d);
|
||||||
|
|
||||||
|
// Test update
|
||||||
|
c.setHeightInches(1);
|
||||||
|
s.flush();
|
||||||
|
heightViaSql = (Double)s.createSQLQuery("select height_centimeters from parentchild c where c.name='Child One'").uniqueResult();
|
||||||
|
assertEquals(2.54d, heightViaSql, 0.01d);
|
||||||
|
s.delete( p );
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,12 @@
|
|||||||
<property name="name" not-null="true"/>
|
<property name="name" not-null="true"/>
|
||||||
<property name="bio"/>
|
<property name="bio"/>
|
||||||
<property name="bioLength" formula="length(bio)"/>
|
<property name="bioLength" formula="length(bio)"/>
|
||||||
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"
|
||||||
|
write="? * 2.54"/>
|
||||||
|
</property>
|
||||||
</composite-element>
|
</composite-element>
|
||||||
</set>
|
</set>
|
||||||
</class>
|
</class>
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
import org.hibernate.dialect.HSQLDialect;
|
import org.hibernate.dialect.HSQLDialect;
|
||||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
@ -57,6 +58,44 @@ public void testCompositeUserType() {
|
|||||||
t.commit();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
Session s = openSession();
|
||||||
|
org.hibernate.Transaction t = s.beginTransaction();
|
||||||
|
final BigDecimal AMOUNT = new BigDecimal(73000000d);
|
||||||
|
final BigDecimal AMOUNT_MILLIONS = AMOUNT.divide(new BigDecimal(1000000d));
|
||||||
|
MutualFund f = new MutualFund();
|
||||||
|
f.setHoldings( new MonetoryAmount( AMOUNT, Currency.getInstance("USD") ) );
|
||||||
|
s.persist(f);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Test value conversion during insert
|
||||||
|
BigDecimal amountViaSql = (BigDecimal)s.createSQLQuery("select amount_millions from MutualFund").uniqueResult();
|
||||||
|
assertEquals(AMOUNT_MILLIONS.doubleValue(), amountViaSql.doubleValue(), 0.01d);
|
||||||
|
|
||||||
|
// Test projection
|
||||||
|
BigDecimal amountViaHql = (BigDecimal)s.createQuery("select f.holdings.amount from MutualFund f").uniqueResult();
|
||||||
|
assertEquals(AMOUNT.doubleValue(), amountViaHql.doubleValue(), 0.01d);
|
||||||
|
|
||||||
|
// Test restriction and entity load via criteria
|
||||||
|
BigDecimal one = new BigDecimal(1);
|
||||||
|
f = (MutualFund)s.createCriteria(MutualFund.class)
|
||||||
|
.add(Restrictions.between("holdings.amount", AMOUNT.subtract(one), AMOUNT.add(one)))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(AMOUNT.doubleValue(), f.getHoldings().getAmount().doubleValue(), 0.01d);
|
||||||
|
|
||||||
|
// Test predicate and entity load via HQL
|
||||||
|
f = (MutualFund)s.createQuery("from MutualFund f where f.holdings.amount between ? and ?")
|
||||||
|
.setBigDecimal(0, AMOUNT.subtract(one))
|
||||||
|
.setBigDecimal(1, AMOUNT.add(one))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(AMOUNT.doubleValue(), f.getHoldings().getAmount().doubleValue(), 0.01d);
|
||||||
|
|
||||||
|
s.delete(f);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.hibernate.test.cut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob.Hasselbaum
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MutualFund {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private MonetoryAmount holdings;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonetoryAmount getHoldings() {
|
||||||
|
return holdings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHoldings(MonetoryAmount holdings) {
|
||||||
|
this.holdings = holdings;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -21,5 +21,18 @@
|
|||||||
<column name="currency" not-null="true"/>
|
<column name="currency" not-null="true"/>
|
||||||
</property>
|
</property>
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
|
<class name="MutualFund" table="MutualFund">
|
||||||
|
<id name="id">
|
||||||
|
<generator class="native"/>
|
||||||
|
</id>
|
||||||
|
<property name="holdings" type="money">
|
||||||
|
<column name="amount_millions"
|
||||||
|
not-null="true"
|
||||||
|
read="amount_millions * 1000000.0"
|
||||||
|
write="? / 1000000.0"/>
|
||||||
|
<column name="currency" not-null="true"/>
|
||||||
|
</property>
|
||||||
|
</class>
|
||||||
|
|
||||||
</hibernate-mapping>
|
</hibernate-mapping>
|
@ -11,21 +11,19 @@
|
|||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.hibernate.Criteria;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.Criteria;
|
|
||||||
import org.hibernate.cache.CacheKey;
|
import org.hibernate.cache.CacheKey;
|
||||||
import org.hibernate.cache.entry.CollectionCacheEntry;
|
import org.hibernate.cache.entry.CollectionCacheEntry;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.criterion.Restrictions;
|
|
||||||
import org.hibernate.criterion.DetachedCriteria;
|
import org.hibernate.criterion.DetachedCriteria;
|
||||||
import org.hibernate.criterion.Property;
|
import org.hibernate.criterion.Property;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
import org.hibernate.criterion.Subqueries;
|
import org.hibernate.criterion.Subqueries;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.impl.SessionFactoryImpl;
|
import org.hibernate.impl.SessionFactoryImpl;
|
||||||
@ -33,6 +31,8 @@
|
|||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of DynamicFilterTest.
|
* Implementation of DynamicFilterTest.
|
||||||
@ -179,6 +179,24 @@ public void testHqlFilters() {
|
|||||||
session.close();
|
session.close();
|
||||||
testData.release();
|
testData.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFiltersWithCustomerReadAndWrite() {
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Custom SQL read/write with filter
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
log.info( "Starting HQL filter with custom SQL get/set tests" );
|
||||||
|
TestData testData = new TestData();
|
||||||
|
testData.prepare();
|
||||||
|
|
||||||
|
Session session = openSession();
|
||||||
|
session.enableFilter( "heavyProducts" ).setParameter("weightKilograms", 4d);
|
||||||
|
log.info( "HQL against Product..." );
|
||||||
|
List results = session.createQuery( "from Product").list();
|
||||||
|
assertEquals( 1, results.size() );
|
||||||
|
|
||||||
|
session.close();
|
||||||
|
testData.release();
|
||||||
|
}
|
||||||
|
|
||||||
public void testCriteriaQueryFilters() {
|
public void testCriteriaQueryFilters() {
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -824,6 +842,7 @@ private void prepare() {
|
|||||||
Product product1 = new Product();
|
Product product1 = new Product();
|
||||||
product1.setName( "Acme Hair Gel" );
|
product1.setName( "Acme Hair Gel" );
|
||||||
product1.setStockNumber( 123 );
|
product1.setStockNumber( 123 );
|
||||||
|
product1.setWeightPounds( 0.25 );
|
||||||
product1.setEffectiveStartDate( lastMonth.getTime() );
|
product1.setEffectiveStartDate( lastMonth.getTime() );
|
||||||
product1.setEffectiveEndDate( nextMonth.getTime() );
|
product1.setEffectiveEndDate( nextMonth.getTime() );
|
||||||
|
|
||||||
@ -848,6 +867,7 @@ private void prepare() {
|
|||||||
Product product2 = new Product();
|
Product product2 = new Product();
|
||||||
product2.setName( "Acme Super-Duper DTO Factory" );
|
product2.setName( "Acme Super-Duper DTO Factory" );
|
||||||
product2.setStockNumber( 124 );
|
product2.setStockNumber( 124 );
|
||||||
|
product1.setWeightPounds( 10.0 );
|
||||||
product2.setEffectiveStartDate( sixMonthsAgo.getTime() );
|
product2.setEffectiveStartDate( sixMonthsAgo.getTime() );
|
||||||
product2.setEffectiveEndDate( new Date() );
|
product2.setEffectiveEndDate( new Date() );
|
||||||
|
|
||||||
|
@ -12,6 +12,12 @@
|
|||||||
|
|
||||||
<property name="name" type="string"/>
|
<property name="name" type="string"/>
|
||||||
<property name="stockNumber" column="STOCK_NUM" type="int"/>
|
<property name="stockNumber" column="STOCK_NUM" type="int"/>
|
||||||
|
<property name="weightPounds">
|
||||||
|
<column name="weight_kg"
|
||||||
|
not-null="true"
|
||||||
|
write="0.453 * ?"
|
||||||
|
read="weight_kg / 0.453"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
<property name="effectiveStartDate" column="eff_start_dt" type="java.util.Date"/>
|
<property name="effectiveStartDate" column="eff_start_dt" type="java.util.Date"/>
|
||||||
<property name="effectiveEndDate" column="eff_end_dt" type="java.util.Date"/>
|
<property name="effectiveEndDate" column="eff_end_dt" type="java.util.Date"/>
|
||||||
@ -30,7 +36,8 @@
|
|||||||
</set>
|
</set>
|
||||||
|
|
||||||
<filter name="effectiveDate" condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>
|
<filter name="effectiveDate" condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>
|
||||||
|
<filter name="heavyProducts" condition=":weightKilograms < weight_kg"/>
|
||||||
|
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
</hibernate-mapping>
|
</hibernate-mapping>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// $Id: Product.java 6507 2005-04-25 16:57:32Z steveebersole $
|
// $Id: Product.java 6507 2005-04-25 16:57:32Z steveebersole $
|
||||||
package org.hibernate.test.filter;
|
package org.hibernate.test.filter;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
@ -14,6 +14,7 @@ public class Product {
|
|||||||
private int stockNumber; // int for ease of hashCode() impl
|
private int stockNumber; // int for ease of hashCode() impl
|
||||||
private Date effectiveStartDate;
|
private Date effectiveStartDate;
|
||||||
private Date effectiveEndDate;
|
private Date effectiveEndDate;
|
||||||
|
private double weightPounds;
|
||||||
private Set orderLineItems;
|
private Set orderLineItems;
|
||||||
private Set categories;
|
private Set categories;
|
||||||
|
|
||||||
@ -73,6 +74,14 @@ public void setEffectiveEndDate(Date effectiveEndDate) {
|
|||||||
this.effectiveEndDate = effectiveEndDate;
|
this.effectiveEndDate = effectiveEndDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getWeightPounds() {
|
||||||
|
return weightPounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeightPounds(double weightPounds) {
|
||||||
|
this.weightPounds = weightPounds;
|
||||||
|
}
|
||||||
|
|
||||||
public Set getCategories() {
|
public Set getCategories() {
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
<filter-param name="asOfDate" type="timestamp"/>
|
<filter-param name="asOfDate" type="timestamp"/>
|
||||||
</filter-def>
|
</filter-def>
|
||||||
|
|
||||||
|
<filter-def name="heavyProducts">
|
||||||
|
<filter-param name="weightKilograms" type="double"/>
|
||||||
|
</filter-def>
|
||||||
|
|
||||||
<filter-def name="seniorSalespersons">
|
<filter-def name="seniorSalespersons">
|
||||||
<filter-param name="asOfDate" type="timestamp"/>
|
<filter-param name="asOfDate" type="timestamp"/>
|
||||||
</filter-def>
|
</filter-def>
|
||||||
@ -31,4 +35,4 @@
|
|||||||
<filter-def name="unioned">
|
<filter-def name="unioned">
|
||||||
</filter-def>
|
</filter-def>
|
||||||
|
|
||||||
</hibernate-mapping>
|
</hibernate-mapping>
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
@ -30,7 +28,6 @@
|
|||||||
import org.hibernate.dialect.HSQLDialect;
|
import org.hibernate.dialect.HSQLDialect;
|
||||||
import org.hibernate.dialect.MySQLDialect;
|
import org.hibernate.dialect.MySQLDialect;
|
||||||
import org.hibernate.dialect.Oracle8iDialect;
|
import org.hibernate.dialect.Oracle8iDialect;
|
||||||
|
|
||||||
import org.hibernate.dialect.PostgreSQLDialect;
|
import org.hibernate.dialect.PostgreSQLDialect;
|
||||||
import org.hibernate.dialect.SQLServerDialect;
|
import org.hibernate.dialect.SQLServerDialect;
|
||||||
import org.hibernate.dialect.Sybase11Dialect;
|
import org.hibernate.dialect.Sybase11Dialect;
|
||||||
@ -55,6 +52,8 @@
|
|||||||
import org.hibernate.type.ManyToOneType;
|
import org.hibernate.type.ManyToOneType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.util.StringHelper;
|
import org.hibernate.util.StringHelper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the integration of the new AST parser into the loading of query results using
|
* Tests the integration of the new AST parser into the loading of query results using
|
||||||
@ -82,6 +81,7 @@ public String[] getMappings() {
|
|||||||
"hql/FooBarCopy.hbm.xml",
|
"hql/FooBarCopy.hbm.xml",
|
||||||
"hql/SimpleEntityWithAssociation.hbm.xml",
|
"hql/SimpleEntityWithAssociation.hbm.xml",
|
||||||
"hql/CrazyIdFieldNames.hbm.xml",
|
"hql/CrazyIdFieldNames.hbm.xml",
|
||||||
|
"hql/Image.hbm.xml",
|
||||||
"batchfetch/ProductLine.hbm.xml",
|
"batchfetch/ProductLine.hbm.xml",
|
||||||
"cid/Customer.hbm.xml",
|
"cid/Customer.hbm.xml",
|
||||||
"cid/Order.hbm.xml",
|
"cid/Order.hbm.xml",
|
||||||
@ -1085,6 +1085,101 @@ public void testComponentOrderBy() {
|
|||||||
t.commit();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testOrderedWithCustomColumnReadAndWrite() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
SimpleEntityWithAssociation first = new SimpleEntityWithAssociation();
|
||||||
|
first.setNegatedNumber(1);
|
||||||
|
s.save(first);
|
||||||
|
SimpleEntityWithAssociation second = new SimpleEntityWithAssociation();
|
||||||
|
second.setNegatedNumber(2);
|
||||||
|
s.save(second);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Check order via SQL. Numbers are negated in the DB, so second comes first.
|
||||||
|
List listViaSql = s.createSQLQuery("select id from simple_1 order by negated_num").list();
|
||||||
|
assertEquals(2, listViaSql.size());
|
||||||
|
assertEquals(second.getId().longValue(), ((Number)listViaSql.get(0)).longValue());
|
||||||
|
assertEquals(first.getId().longValue(), ((Number)listViaSql.get(1)).longValue());
|
||||||
|
|
||||||
|
// Check order via HQL. Now first comes first b/c the read negates the DB negation.
|
||||||
|
List listViaHql = s.createQuery("from SimpleEntityWithAssociation order by negatedNumber").list();
|
||||||
|
assertEquals(2, listViaHql.size());
|
||||||
|
assertEquals(first.getId(), ((SimpleEntityWithAssociation)listViaHql.get(0)).getId());
|
||||||
|
assertEquals(second.getId(), ((SimpleEntityWithAssociation)listViaHql.get(1)).getId());
|
||||||
|
|
||||||
|
s.delete(first);
|
||||||
|
s.delete(second);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testHavingWithCustomColumnReadAndWrite() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
SimpleEntityWithAssociation first = new SimpleEntityWithAssociation();
|
||||||
|
first.setNegatedNumber(5);
|
||||||
|
first.setName("simple");
|
||||||
|
s.save(first);
|
||||||
|
SimpleEntityWithAssociation second = new SimpleEntityWithAssociation();
|
||||||
|
second.setNegatedNumber(10);
|
||||||
|
second.setName("simple");
|
||||||
|
s.save(second);
|
||||||
|
SimpleEntityWithAssociation third = new SimpleEntityWithAssociation();
|
||||||
|
third.setNegatedNumber(20);
|
||||||
|
third.setName("complex");
|
||||||
|
s.save(third);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Check order via HQL. Now first comes first b/c the read negates the DB negation.
|
||||||
|
Number r = (Number)s.createQuery("select sum(negatedNumber) from SimpleEntityWithAssociation " +
|
||||||
|
"group by name having sum(negatedNumber) < 20").uniqueResult();
|
||||||
|
assertEquals(r.intValue(), 15);
|
||||||
|
|
||||||
|
s.delete(first);
|
||||||
|
s.delete(second);
|
||||||
|
s.delete(third);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLoadSnapshotWithCustomColumnReadAndWrite() {
|
||||||
|
// Exercises entity snapshot load when select-before-update is true.
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
final double SIZE_IN_KB = 1536d;
|
||||||
|
final double SIZE_IN_MB = SIZE_IN_KB / 1024d;
|
||||||
|
Image image = new Image();
|
||||||
|
image.setName("picture.gif");
|
||||||
|
image.setSizeKb(SIZE_IN_KB);
|
||||||
|
s.persist(image);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
Double sizeViaSql = (Double)s.createSQLQuery("select size_mb from image").uniqueResult();
|
||||||
|
assertEquals(SIZE_IN_MB, sizeViaSql, 0.01d);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
t = s.beginTransaction();
|
||||||
|
final double NEW_SIZE_IN_KB = 2048d;
|
||||||
|
final double NEW_SIZE_IN_MB = NEW_SIZE_IN_KB / 1024d;
|
||||||
|
image.setSizeKb(NEW_SIZE_IN_KB);
|
||||||
|
s.update(image);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
sizeViaSql = (Double)s.createSQLQuery("select size_mb from image").uniqueResult();
|
||||||
|
assertEquals(NEW_SIZE_IN_MB, sizeViaSql, 0.01d);
|
||||||
|
|
||||||
|
s.delete(image);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Human genSimpleHuman(String fName, String lName) {
|
private Human genSimpleHuman(String fName, String lName) {
|
||||||
Human h = new Human();
|
Human h = new Human();
|
||||||
@ -1188,13 +1283,13 @@ public void testAggregation() {
|
|||||||
Transaction t = s.beginTransaction();
|
Transaction t = s.beginTransaction();
|
||||||
Human h = new Human();
|
Human h = new Human();
|
||||||
h.setBodyWeight( (float) 74.0 );
|
h.setBodyWeight( (float) 74.0 );
|
||||||
h.setHeight(120.5);
|
h.setHeightInches(120.5);
|
||||||
h.setDescription("Me");
|
h.setDescription("Me");
|
||||||
h.setName( new Name("Gavin", 'A', "King") );
|
h.setName( new Name("Gavin", 'A', "King") );
|
||||||
h.setNickName("Oney");
|
h.setNickName("Oney");
|
||||||
s.persist(h);
|
s.persist(h);
|
||||||
Double sum = (Double) s.createQuery("select sum(h.bodyWeight) from Human h").uniqueResult();
|
Double sum = (Double) s.createQuery("select sum(h.bodyWeight) from Human h").uniqueResult();
|
||||||
Double avg = (Double) s.createQuery("select avg(h.height) from Human h").uniqueResult();
|
Double avg = (Double) s.createQuery("select avg(h.heightInches) from Human h").uniqueResult(); // uses custom read and write for column
|
||||||
assertEquals(sum.floatValue(), 74.0, 0.01);
|
assertEquals(sum.floatValue(), 74.0, 0.01);
|
||||||
assertEquals(avg.doubleValue(), 120.5, 0.01);
|
assertEquals(avg.doubleValue(), 120.5, 0.01);
|
||||||
Long id = (Long) s.createQuery("select max(a.id) from Animal a").uniqueResult();
|
Long id = (Long) s.createQuery("select max(a.id) from Animal a").uniqueResult();
|
||||||
@ -1208,7 +1303,7 @@ public void testSelectClauseCase() {
|
|||||||
Transaction t = s.beginTransaction();
|
Transaction t = s.beginTransaction();
|
||||||
Human h = new Human();
|
Human h = new Human();
|
||||||
h.setBodyWeight( (float) 74.0 );
|
h.setBodyWeight( (float) 74.0 );
|
||||||
h.setHeight(120.5);
|
h.setHeightInches(120.5);
|
||||||
h.setDescription("Me");
|
h.setDescription("Me");
|
||||||
h.setName( new Name("Gavin", 'A', "King") );
|
h.setName( new Name("Gavin", 'A', "King") );
|
||||||
h.setNickName("Oney");
|
h.setNickName("Oney");
|
||||||
@ -1395,6 +1490,40 @@ public void testManyToManyFilter() throws Throwable {
|
|||||||
txn.commit();
|
txn.commit();
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFilterWithCustomColumnReadAndWrite() {
|
||||||
|
Session session = openSession();
|
||||||
|
Transaction txn = session.beginTransaction();
|
||||||
|
|
||||||
|
Human human = new Human();
|
||||||
|
human.setName( new Name( "Steve", 'L', "Ebersole" ) );
|
||||||
|
human.setHeightInches(73d);
|
||||||
|
session.save( human );
|
||||||
|
|
||||||
|
Human friend = new Human();
|
||||||
|
friend.setName( new Name( "John", 'Q', "Doe" ) );
|
||||||
|
friend.setHeightInches(50d);
|
||||||
|
session.save( friend );
|
||||||
|
|
||||||
|
human.setFriends( new ArrayList() );
|
||||||
|
friend.setFriends( new ArrayList() );
|
||||||
|
human.getFriends().add( friend );
|
||||||
|
friend.getFriends().add( human );
|
||||||
|
|
||||||
|
session.flush();
|
||||||
|
|
||||||
|
assertEquals( session.createFilter( human.getFriends(), "" ).list().size(), 1 );
|
||||||
|
assertEquals( session.createFilter( human.getFriends(), "where this.heightInches < ?" ).setDouble( 0, 51d ).list().size(), 1 );
|
||||||
|
assertEquals( session.createFilter( human.getFriends(), "where this.heightInches > ?" ).setDouble( 0, 51d ).list().size(), 0 );
|
||||||
|
assertEquals( session.createFilter( human.getFriends(), "where this.heightInches between 49 and 51" ).list().size(), 1 );
|
||||||
|
assertEquals( session.createFilter( human.getFriends(), "where this.heightInches not between 49 and 51" ).list().size(), 0 );
|
||||||
|
|
||||||
|
session.delete(human);
|
||||||
|
session.delete(friend);
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
public void testSelectExpressions() {
|
public void testSelectExpressions() {
|
||||||
createTestBaseData();
|
createTestBaseData();
|
||||||
|
@ -47,8 +47,12 @@
|
|||||||
<property name="last" column="name_last"/>
|
<property name="last" column="name_last"/>
|
||||||
</component>
|
</component>
|
||||||
<property name="nickName"/>
|
<property name="nickName"/>
|
||||||
<property name="height"/>
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"
|
||||||
|
write="? * 2.54"/>
|
||||||
|
</property>
|
||||||
<property name="intValue"/>
|
<property name="intValue"/>
|
||||||
<property name="floatValue"/>
|
<property name="floatValue"/>
|
||||||
<property name="bigDecimalValue"/>
|
<property name="bigDecimalValue"/>
|
||||||
@ -147,4 +151,4 @@
|
|||||||
</join>
|
</join>
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
</hibernate-mapping>
|
</hibernate-mapping>
|
||||||
|
@ -43,12 +43,12 @@ public void testClassicHQLAggregationReturnTypes() {
|
|||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.INTEGER, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.INTEGER, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
translator = createNewQueryTranslator( "select count(h.height) from Human h", sfi() );
|
translator = createNewQueryTranslator( "select count(h.heightInches) from Human h", sfi() );
|
||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.INTEGER, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.INTEGER, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
// MAX, MIN return the type of the state-field to which they are applied.
|
// MAX, MIN return the type of the state-field to which they are applied.
|
||||||
translator = createNewQueryTranslator( "select max(h.height) from Human h", sfi() );
|
translator = createNewQueryTranslator( "select max(h.heightInches) from Human h", sfi() );
|
||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ public void testClassicHQLAggregationReturnTypes() {
|
|||||||
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
// AVG returns Float integrals, and otherwise the field type.
|
// AVG returns Float integrals, and otherwise the field type.
|
||||||
translator = createNewQueryTranslator( "select avg(h.height) from Human h", sfi() );
|
translator = createNewQueryTranslator( "select avg(h.heightInches) from Human h", sfi() );
|
||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ public void testClassicHQLAggregationReturnTypes() {
|
|||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.INTEGER, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.INTEGER, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
translator = createNewQueryTranslator( "select sum(h.height) from Human h", sfi() );
|
translator = createNewQueryTranslator( "select sum(h.heightInches) from Human h", sfi() );
|
||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
|
@ -47,12 +47,12 @@ public void testHQLAggregationReturnType() {
|
|||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
translator = createNewQueryTranslator( "select count(h.height) from Human h" );
|
translator = createNewQueryTranslator( "select count(h.heightInches) from Human h" );
|
||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
// MAX, MIN return the type of the state-field to which they are applied.
|
// MAX, MIN return the type of the state-field to which they are applied.
|
||||||
translator = createNewQueryTranslator( "select max(h.height) from Human h" );
|
translator = createNewQueryTranslator( "select max(h.heightInches) from Human h" );
|
||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ public void testHQLAggregationReturnType() {
|
|||||||
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
// AVG returns Double.
|
// AVG returns Double.
|
||||||
translator = createNewQueryTranslator( "select avg(h.height) from Human h" );
|
translator = createNewQueryTranslator( "select avg(h.heightInches) from Human h" );
|
||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ public void testHQLAggregationReturnType() {
|
|||||||
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.LONG, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
// SUM returns Double when applied to state-fields of floating point types;
|
// SUM returns Double when applied to state-fields of floating point types;
|
||||||
translator = createNewQueryTranslator( "select sum(h.height) from Human h" );
|
translator = createNewQueryTranslator( "select sum(h.heightInches) from Human h" );
|
||||||
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
assertEquals( "incorrect return type count", 1, translator.getReturnTypes().length );
|
||||||
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
assertEquals( "incorrect return type", Hibernate.DOUBLE, translator.getReturnTypes()[0] );
|
||||||
|
|
||||||
@ -123,18 +123,18 @@ public void testCriteriaAggregationReturnTypeFailureExpected() {
|
|||||||
// EJB3: COUNT returns Long
|
// EJB3: COUNT returns Long
|
||||||
Long longValue = (Long) s.createCriteria( Human.class ).setProjection( Projections.rowCount()).uniqueResult();
|
Long longValue = (Long) s.createCriteria( Human.class ).setProjection( Projections.rowCount()).uniqueResult();
|
||||||
assertEquals(longValue, new Long(1));
|
assertEquals(longValue, new Long(1));
|
||||||
longValue = (Long) s.createCriteria( Human.class ).setProjection( Projections.count("height")).uniqueResult();
|
longValue = (Long) s.createCriteria( Human.class ).setProjection( Projections.count("heightInches")).uniqueResult();
|
||||||
assertEquals(longValue, new Long(1));
|
assertEquals(longValue, new Long(1));
|
||||||
|
|
||||||
// MAX, MIN return the type of the state-field to which they are applied.
|
// MAX, MIN return the type of the state-field to which they are applied.
|
||||||
Double dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.max( "height" )).uniqueResult();
|
Double dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.max( "heightInches" )).uniqueResult();
|
||||||
assertNotNull(dblValue);
|
assertNotNull(dblValue);
|
||||||
|
|
||||||
longValue = (Long) s.createCriteria( Human.class ).setProjection( Projections.max( "id" )).uniqueResult();
|
longValue = (Long) s.createCriteria( Human.class ).setProjection( Projections.max( "id" )).uniqueResult();
|
||||||
assertNotNull(longValue);
|
assertNotNull(longValue);
|
||||||
|
|
||||||
// AVG returns Double.
|
// AVG returns Double.
|
||||||
dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.avg( "height" )).uniqueResult();
|
dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.avg( "heightInches" )).uniqueResult();
|
||||||
assertNotNull(dblValue);
|
assertNotNull(dblValue);
|
||||||
|
|
||||||
dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.avg( "id" )).uniqueResult();
|
dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.avg( "id" )).uniqueResult();
|
||||||
@ -151,7 +151,7 @@ public void testCriteriaAggregationReturnTypeFailureExpected() {
|
|||||||
assertNotNull(longValue);
|
assertNotNull(longValue);
|
||||||
|
|
||||||
// SUM returns Double when applied to state-fields of floating point types;
|
// SUM returns Double when applied to state-fields of floating point types;
|
||||||
dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.sum( "height" )).uniqueResult();
|
dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.sum( "heightInches" )).uniqueResult();
|
||||||
assertNotNull(dblValue);
|
assertNotNull(dblValue);
|
||||||
|
|
||||||
dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.sum( "floatValue" )).uniqueResult();
|
dblValue = (Double) s.createCriteria( Human.class ).setProjection( Projections.sum( "floatValue" )).uniqueResult();
|
||||||
|
@ -16,7 +16,7 @@ public class Human extends Mammal {
|
|||||||
private Collection friends;
|
private Collection friends;
|
||||||
private Collection pets;
|
private Collection pets;
|
||||||
private Map family;
|
private Map family;
|
||||||
private double height;
|
private double heightInches;
|
||||||
|
|
||||||
private BigInteger bigIntegerValue;
|
private BigInteger bigIntegerValue;
|
||||||
private BigDecimal bigDecimalValue;
|
private BigDecimal bigDecimalValue;
|
||||||
@ -58,11 +58,12 @@ public void setNickName(String nickName) {
|
|||||||
this.nickName = nickName;
|
this.nickName = nickName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getHeight() {
|
public double getHeightInches() {
|
||||||
return height;
|
return heightInches;
|
||||||
}
|
}
|
||||||
public void setHeight(double height) {
|
|
||||||
this.height = height;
|
public void setHeightInches(double height) {
|
||||||
|
this.heightInches = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map getFamily() {
|
public Map getFamily() {
|
||||||
|
20
testsuite/src/test/java/org/hibernate/test/hql/Image.hbm.xml
Normal file
20
testsuite/src/test/java/org/hibernate/test/hql/Image.hbm.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
|
||||||
|
|
||||||
|
<hibernate-mapping package="org.hibernate.test.hql">
|
||||||
|
|
||||||
|
<class name="Image" table="image" select-before-update="true" >
|
||||||
|
<id name="id" type="java.lang.Long" column="id">
|
||||||
|
<generator class="native"/>
|
||||||
|
</id>
|
||||||
|
<property name="name" type="java.lang.String" column="name"/>
|
||||||
|
<property name="sizeKb" lazy="true">
|
||||||
|
<column name="size_mb"
|
||||||
|
read="size_mb * 1024.0"
|
||||||
|
write="? / 1024.0"/>
|
||||||
|
</property>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
49
testsuite/src/test/java/org/hibernate/test/hql/Image.java
Normal file
49
testsuite/src/test/java/org/hibernate/test/hql/Image.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package org.hibernate.test.hql;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob.Hasselbaum
|
||||||
|
*/
|
||||||
|
public class Image {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private double sizeKb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param id the id to set
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param name the name to set
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the size in kb
|
||||||
|
*/
|
||||||
|
public double getSizeKb() {
|
||||||
|
return sizeKb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param sizeKb the size in kb to set
|
||||||
|
*/
|
||||||
|
public void setSizeKb(double sizeKb) {
|
||||||
|
this.sizeKb = sizeKb;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -11,6 +11,11 @@
|
|||||||
<generator class="native"/>
|
<generator class="native"/>
|
||||||
</id>
|
</id>
|
||||||
<property name="name" column="NAME" type="string"/>
|
<property name="name" column="NAME" type="string"/>
|
||||||
|
<property name="negatedNumber">
|
||||||
|
<column name="negated_num"
|
||||||
|
read="-negated_num"
|
||||||
|
write="0 - ?"/>
|
||||||
|
</property>
|
||||||
<set name="associatedEntities" cascade="all" inverse="true" lazy="true">
|
<set name="associatedEntities" cascade="all" inverse="true" lazy="true">
|
||||||
<key column="SIMPLE_1_ID"/>
|
<key column="SIMPLE_1_ID"/>
|
||||||
<one-to-many class="SimpleAssociatedEntity"/>
|
<one-to-many class="SimpleAssociatedEntity"/>
|
||||||
@ -29,4 +34,4 @@
|
|||||||
<many-to-one name="owner" class="SimpleEntityWithAssociation" column="SIMPLE_1_ID"/>
|
<many-to-one name="owner" class="SimpleEntityWithAssociation" column="SIMPLE_1_ID"/>
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
</hibernate-mapping>
|
</hibernate-mapping>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.hibernate.test.hql;
|
package org.hibernate.test.hql;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
@ -9,6 +9,7 @@
|
|||||||
public class SimpleEntityWithAssociation {
|
public class SimpleEntityWithAssociation {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
|
private Integer negatedNumber;
|
||||||
private Set associatedEntities = new HashSet();
|
private Set associatedEntities = new HashSet();
|
||||||
private Set manyToManyAssociatedEntities = new HashSet();
|
private Set manyToManyAssociatedEntities = new HashSet();
|
||||||
|
|
||||||
@ -34,6 +35,14 @@ public String getName() {
|
|||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getNegatedNumber() {
|
||||||
|
return negatedNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNegatedNumber(Integer negatedNumber) {
|
||||||
|
this.negatedNumber = negatedNumber;
|
||||||
|
}
|
||||||
|
|
||||||
public Set getAssociatedEntities() {
|
public Set getAssociatedEntities() {
|
||||||
return associatedEntities;
|
return associatedEntities;
|
||||||
|
@ -5,18 +5,19 @@
|
|||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
import org.hibernate.intercept.FieldInterceptionHelper;
|
import org.hibernate.intercept.FieldInterceptionHelper;
|
||||||
import org.hibernate.test.instrument.domain.Document;
|
import org.hibernate.junit.UnitTestCase;
|
||||||
|
import org.hibernate.test.instrument.cases.Executable;
|
||||||
|
import org.hibernate.test.instrument.cases.TestCustomColumnReadAndWrite;
|
||||||
import org.hibernate.test.instrument.cases.TestDirtyCheckExecutable;
|
import org.hibernate.test.instrument.cases.TestDirtyCheckExecutable;
|
||||||
import org.hibernate.test.instrument.cases.TestFetchAllExecutable;
|
import org.hibernate.test.instrument.cases.TestFetchAllExecutable;
|
||||||
import org.hibernate.test.instrument.cases.TestLazyExecutable;
|
|
||||||
import org.hibernate.test.instrument.cases.TestLazyManyToOneExecutable;
|
|
||||||
import org.hibernate.test.instrument.cases.TestInjectFieldInterceptorExecutable;
|
import org.hibernate.test.instrument.cases.TestInjectFieldInterceptorExecutable;
|
||||||
import org.hibernate.test.instrument.cases.TestIsPropertyInitializedExecutable;
|
import org.hibernate.test.instrument.cases.TestIsPropertyInitializedExecutable;
|
||||||
|
import org.hibernate.test.instrument.cases.TestLazyExecutable;
|
||||||
|
import org.hibernate.test.instrument.cases.TestLazyManyToOneExecutable;
|
||||||
import org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable;
|
import org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable;
|
||||||
import org.hibernate.test.instrument.cases.TestManyToOneProxyExecutable;
|
import org.hibernate.test.instrument.cases.TestManyToOneProxyExecutable;
|
||||||
import org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable;
|
import org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable;
|
||||||
import org.hibernate.test.instrument.cases.Executable;
|
import org.hibernate.test.instrument.domain.Document;
|
||||||
import org.hibernate.junit.UnitTestCase;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
@ -67,6 +68,10 @@ public void testSharedPKOneToOne() throws Exception {
|
|||||||
execute( new TestSharedPKOneToOneExecutable() );
|
execute( new TestSharedPKOneToOneExecutable() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() throws Exception {
|
||||||
|
execute( new TestCustomColumnReadAndWrite() );
|
||||||
|
}
|
||||||
|
|
||||||
private void execute(Executable executable) throws Exception {
|
private void execute(Executable executable) throws Exception {
|
||||||
executable.prepare();
|
executable.prepare();
|
||||||
try {
|
try {
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
package org.hibernate.test.instrument.cases;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.classic.Session;
|
||||||
|
import org.hibernate.test.instrument.domain.Document;
|
||||||
|
import org.hibernate.test.instrument.domain.Folder;
|
||||||
|
import org.hibernate.test.instrument.domain.Owner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rob.Hasselbaum
|
||||||
|
*/
|
||||||
|
public class TestCustomColumnReadAndWrite extends AbstractExecutable {
|
||||||
|
public void execute() {
|
||||||
|
Session s = getFactory().openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
final double SIZE_IN_KB = 20480;
|
||||||
|
final double SIZE_IN_MB = SIZE_IN_KB / 1024d;
|
||||||
|
Owner o = new Owner();
|
||||||
|
Document doc = new Document();
|
||||||
|
Folder fol = new Folder();
|
||||||
|
o.setName("gavin");
|
||||||
|
doc.setName("Hibernate in Action");
|
||||||
|
doc.setSummary("blah");
|
||||||
|
doc.updateText("blah blah");
|
||||||
|
fol.setName("books");
|
||||||
|
doc.setOwner(o);
|
||||||
|
doc.setFolder(fol);
|
||||||
|
doc.setSizeKb(SIZE_IN_KB);
|
||||||
|
fol.getDocuments().add(doc);
|
||||||
|
s.persist(o);
|
||||||
|
s.persist(fol);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
s = getFactory().openSession();
|
||||||
|
t = s.beginTransaction();
|
||||||
|
|
||||||
|
// Check value conversion on insert
|
||||||
|
Double sizeViaSql = (Double)s.createSQLQuery("select size_mb from documents").uniqueResult();
|
||||||
|
assertEquals( SIZE_IN_MB, sizeViaSql, 0.01d );
|
||||||
|
|
||||||
|
// Test explicit fetch of all properties
|
||||||
|
doc = (Document) s.createQuery("from Document fetch all properties").uniqueResult();
|
||||||
|
assertTrue( Hibernate.isPropertyInitialized( doc, "sizeKb" ) );
|
||||||
|
assertEquals( SIZE_IN_KB, doc.getSizeKb() );
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
// Test lazy fetch with custom read
|
||||||
|
s = getFactory().openSession();
|
||||||
|
t = s.beginTransaction();
|
||||||
|
doc = (Document) s.get( Document.class, doc.getId() );
|
||||||
|
assertFalse( Hibernate.isPropertyInitialized( doc, "sizeKb" ) );
|
||||||
|
assertEquals( SIZE_IN_KB, doc.getSizeKb() );
|
||||||
|
s.delete(doc);
|
||||||
|
s.delete( doc.getOwner() );
|
||||||
|
s.delete( doc.getFolder() );
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ public class Document {
|
|||||||
private String text;
|
private String text;
|
||||||
private Owner owner;
|
private Owner owner;
|
||||||
private Folder folder;
|
private Folder folder;
|
||||||
|
private double sizeKb;
|
||||||
private Date lastTextModification = new Date();
|
private Date lastTextModification = new Date();
|
||||||
/**
|
/**
|
||||||
* @return Returns the folder.
|
* @return Returns the folder.
|
||||||
@ -99,6 +100,18 @@ public String getUpperCaseName() {
|
|||||||
public void setUpperCaseName(String upperCaseName) {
|
public void setUpperCaseName(String upperCaseName) {
|
||||||
this.upperCaseName = upperCaseName;
|
this.upperCaseName = upperCaseName;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @param sizeKb The size in KBs.
|
||||||
|
*/
|
||||||
|
public void setSizeKb(double sizeKb) {
|
||||||
|
this.sizeKb = sizeKb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return The size in KBs.
|
||||||
|
*/
|
||||||
|
public double getSizeKb() {
|
||||||
|
return sizeKb;
|
||||||
|
}
|
||||||
|
|
||||||
public void updateText(String newText) {
|
public void updateText(String newText) {
|
||||||
if ( !newText.equals(text) ) {
|
if ( !newText.equals(text) ) {
|
||||||
|
@ -53,6 +53,11 @@
|
|||||||
<many-to-one name="owner" not-null="true" lazy="no-proxy" fetch="select"/>
|
<many-to-one name="owner" not-null="true" lazy="no-proxy" fetch="select"/>
|
||||||
<property name="text" not-null="true" length="2000" lazy="true"/>
|
<property name="text" not-null="true" length="2000" lazy="true"/>
|
||||||
<property name="lastTextModification" not-null="true" lazy="true" access="field"/>
|
<property name="lastTextModification" not-null="true" lazy="true" access="field"/>
|
||||||
|
<property name="sizeKb" lazy="true">
|
||||||
|
<column name="size_mb"
|
||||||
|
read="size_mb * 1024.0"
|
||||||
|
write="? / 1024.0"/>
|
||||||
|
</property>
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
<class name="Entity" table="entity">
|
<class name="Entity" table="entity">
|
||||||
|
@ -82,6 +82,10 @@ public void testSharedPKOneToOne() {
|
|||||||
executeExecutable( "org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable" );
|
executeExecutable( "org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
executeExecutable( "org.hibernate.test.instrument.cases.TestCustomColumnReadAndWrite" );
|
||||||
|
}
|
||||||
|
|
||||||
// reflection code to ensure isolation into the created classloader ~~~~~~~
|
// reflection code to ensure isolation into the created classloader ~~~~~~~
|
||||||
|
|
||||||
private static final Class[] SIG = new Class[] {};
|
private static final Class[] SIG = new Class[] {};
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package org.hibernate.test.instrument.runtime;
|
package org.hibernate.test.instrument.runtime;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
import org.hibernate.bytecode.BytecodeProvider;
|
import org.hibernate.bytecode.BytecodeProvider;
|
||||||
import org.hibernate.bytecode.cglib.BytecodeProviderImpl;
|
import org.hibernate.bytecode.cglib.BytecodeProviderImpl;
|
||||||
import junit.framework.Test;
|
|
||||||
import junit.framework.TestSuite;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
@ -52,4 +53,9 @@ public void testManyToOneProxy() {
|
|||||||
public void testSharedPKOneToOne() {
|
public void testSharedPKOneToOne() {
|
||||||
super.testSharedPKOneToOne();
|
super.testSharedPKOneToOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
super.testCustomColumnReadAndWrite();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
//$Id: $
|
//$Id: $
|
||||||
package org.hibernate.test.instrument.runtime;
|
package org.hibernate.test.instrument.runtime;
|
||||||
|
|
||||||
import org.hibernate.bytecode.BytecodeProvider;
|
|
||||||
import org.hibernate.bytecode.javassist.BytecodeProviderImpl;
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.hibernate.bytecode.BytecodeProvider;
|
||||||
|
import org.hibernate.bytecode.javassist.BytecodeProviderImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@ -53,4 +54,9 @@ public void testManyToOneProxy() {
|
|||||||
public void testSharedPKOneToOne() {
|
public void testSharedPKOneToOne() {
|
||||||
super.testSharedPKOneToOne();
|
super.testSharedPKOneToOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
super.testCustomColumnReadAndWrite();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
|
|
||||||
@ -130,6 +131,82 @@ public void testSequentialSelectsOptionalData() throws Exception {
|
|||||||
t.commit();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
final double HEIGHT_INCHES = 73;
|
||||||
|
final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d;
|
||||||
|
Person p = new Person();
|
||||||
|
p.setName("Emmanuel");
|
||||||
|
p.setSex('M');
|
||||||
|
p.setHeightInches(HEIGHT_INCHES);
|
||||||
|
s.persist(p);
|
||||||
|
final double PASSWORD_EXPIRY_WEEKS = 4;
|
||||||
|
final double PASSWORD_EXPIRY_DAYS = PASSWORD_EXPIRY_WEEKS * 7d;
|
||||||
|
User u = new User();
|
||||||
|
u.setName("Steve");
|
||||||
|
u.setSex('M');
|
||||||
|
u.setPasswordExpiryDays(PASSWORD_EXPIRY_DAYS);
|
||||||
|
s.persist(u);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Test value conversion during insert
|
||||||
|
Double heightViaSql = (Double)s.createSQLQuery("select height_centimeters from person where name='Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
|
||||||
|
Double expiryViaSql = (Double)s.createSQLQuery("select pwd_expiry_weeks from t_user where person_id=?")
|
||||||
|
.setLong(0, u.getId())
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_WEEKS, expiryViaSql, 0.01d);
|
||||||
|
|
||||||
|
// Test projection
|
||||||
|
Double heightViaHql = (Double)s.createQuery("select p.heightInches from Person p where p.name = 'Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, heightViaHql, 0.01d);
|
||||||
|
Double expiryViaHql = (Double)s.createQuery("select u.passwordExpiryDays from User u where u.name = 'Steve'").uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, expiryViaHql, 0.01d);
|
||||||
|
|
||||||
|
// Test restriction and entity load via criteria
|
||||||
|
p = (Person)s.createCriteria(Person.class)
|
||||||
|
.add(Restrictions.between("heightInches", HEIGHT_INCHES - 0.01d, HEIGHT_INCHES + 0.01d))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, p.getHeightInches(), 0.01d);
|
||||||
|
u = (User)s.createCriteria(User.class)
|
||||||
|
.add(Restrictions.between("passwordExpiryDays", PASSWORD_EXPIRY_DAYS - 0.01d, PASSWORD_EXPIRY_DAYS + 0.01d))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, u.getPasswordExpiryDays(), 0.01d);
|
||||||
|
|
||||||
|
// Test predicate and entity load via HQL
|
||||||
|
p = (Person)s.createQuery("from Person p where p.heightInches between ? and ?")
|
||||||
|
.setDouble(0, HEIGHT_INCHES - 0.01d)
|
||||||
|
.setDouble(1, HEIGHT_INCHES + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, p.getHeightInches(), 0.01d);
|
||||||
|
u = (User)s.createQuery("from User u where u.passwordExpiryDays between ? and ?")
|
||||||
|
.setDouble(0, PASSWORD_EXPIRY_DAYS - 0.01d)
|
||||||
|
.setDouble(1, PASSWORD_EXPIRY_DAYS + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, u.getPasswordExpiryDays(), 0.01d);
|
||||||
|
|
||||||
|
// Test update
|
||||||
|
p.setHeightInches(1);
|
||||||
|
u.setPasswordExpiryDays(7d);
|
||||||
|
s.flush();
|
||||||
|
heightViaSql = (Double)s.createSQLQuery("select height_centimeters from person where name='Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(2.54d, heightViaSql, 0.01d);
|
||||||
|
expiryViaSql = (Double)s.createSQLQuery("select pwd_expiry_weeks from t_user where person_id=?")
|
||||||
|
.setLong(0, u.getId())
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(1d, expiryViaSql, 0.01d);
|
||||||
|
|
||||||
|
s.delete(p);
|
||||||
|
s.delete(u);
|
||||||
|
assertTrue( s.createQuery("from Person").list().isEmpty() );
|
||||||
|
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,12 @@
|
|||||||
|
|
||||||
<property name="name" not-null="true" length="80"/>
|
<property name="name" not-null="true" length="80"/>
|
||||||
<property name="sex" not-null="true" update="false"/>
|
<property name="sex" not-null="true" update="false"/>
|
||||||
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"
|
||||||
|
write="? * 2.54"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
<join table="address">
|
<join table="address">
|
||||||
<key column="address_id"/>
|
<key column="address_id"/>
|
||||||
@ -65,6 +71,11 @@
|
|||||||
<join table="t_user" fetch="select" optional="true">
|
<join table="t_user" fetch="select" optional="true">
|
||||||
<key column="person_id"/>
|
<key column="person_id"/>
|
||||||
<property name="login" column="u_login"/>
|
<property name="login" column="u_login"/>
|
||||||
|
<property name="passwordExpiryDays">
|
||||||
|
<column name="pwd_expiry_weeks"
|
||||||
|
read="pwd_expiry_weeks * 7.0"
|
||||||
|
write="? / 7.0"/>
|
||||||
|
</property>
|
||||||
</join>
|
</join>
|
||||||
<join table="t_silly" fetch="select" optional="true">
|
<join table="t_silly" fetch="select" optional="true">
|
||||||
<key column="person_id"/>
|
<key column="person_id"/>
|
||||||
|
@ -11,6 +11,7 @@ public class Person {
|
|||||||
private String address;
|
private String address;
|
||||||
private String zip;
|
private String zip;
|
||||||
private String country;
|
private String country;
|
||||||
|
private double heightInches;
|
||||||
private char sex;
|
private char sex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,6 +78,18 @@ public String getZip() {
|
|||||||
public void setZip(String zip) {
|
public void setZip(String zip) {
|
||||||
this.zip = zip;
|
this.zip = zip;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return the The height in inches.
|
||||||
|
*/
|
||||||
|
public double getHeightInches() {
|
||||||
|
return heightInches;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param heightInches The height in inches.
|
||||||
|
*/
|
||||||
|
public void setHeightInches(double heightInches) {
|
||||||
|
this.heightInches = heightInches;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @param address The address to set.
|
* @param address The address to set.
|
||||||
*/
|
*/
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
public class User extends Person {
|
public class User extends Person {
|
||||||
private String login;
|
private String login;
|
||||||
private String silly;
|
private String silly;
|
||||||
|
private Double passwordExpiryDays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the login.
|
* @return Returns the login.
|
||||||
@ -20,4 +21,16 @@ public String getLogin() {
|
|||||||
public void setLogin(String login) {
|
public void setLogin(String login) {
|
||||||
this.login = login;
|
this.login = login;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return The password expiry policy in days.
|
||||||
|
*/
|
||||||
|
public Double getPasswordExpiryDays() {
|
||||||
|
return passwordExpiryDays;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param passwordExpiryDays The password expiry policy in days.
|
||||||
|
*/
|
||||||
|
public void setPasswordExpiryDays(Double passwordExpiryDays) {
|
||||||
|
this.passwordExpiryDays = passwordExpiryDays;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
public class Employee extends Person {
|
public class Employee extends Person {
|
||||||
private String title;
|
private String title;
|
||||||
private BigDecimal salary;
|
private BigDecimal salary;
|
||||||
|
private double passwordExpiryDays;
|
||||||
private Employee manager;
|
private Employee manager;
|
||||||
/**
|
/**
|
||||||
* @return Returns the title.
|
* @return Returns the title.
|
||||||
@ -46,4 +47,16 @@ public BigDecimal getSalary() {
|
|||||||
public void setSalary(BigDecimal salary) {
|
public void setSalary(BigDecimal salary) {
|
||||||
this.salary = salary;
|
this.salary = salary;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return The password expiry policy in days.
|
||||||
|
*/
|
||||||
|
public double getPasswordExpiryDays() {
|
||||||
|
return passwordExpiryDays;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param passwordExpiryDays The password expiry policy in days.
|
||||||
|
*/
|
||||||
|
public void setPasswordExpiryDays(double passwordExpiryDays) {
|
||||||
|
this.passwordExpiryDays = passwordExpiryDays;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,6 +179,79 @@ public void testQuerySubclassAttribute() {
|
|||||||
t.commit();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
final double HEIGHT_INCHES = 73;
|
||||||
|
final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d;
|
||||||
|
Person p = new Person();
|
||||||
|
p.setName("Emmanuel");
|
||||||
|
p.setSex('M');
|
||||||
|
p.setHeightInches(HEIGHT_INCHES);
|
||||||
|
s.persist(p);
|
||||||
|
final double PASSWORD_EXPIRY_WEEKS = 4;
|
||||||
|
final double PASSWORD_EXPIRY_DAYS = PASSWORD_EXPIRY_WEEKS * 7d;
|
||||||
|
Employee e = new Employee();
|
||||||
|
e.setName("Steve");
|
||||||
|
e.setSex('M');
|
||||||
|
e.setTitle("Mr");
|
||||||
|
e.setPasswordExpiryDays(PASSWORD_EXPIRY_DAYS);
|
||||||
|
s.persist(e);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Test value conversion during insert
|
||||||
|
Double heightViaSql = (Double)s.createSQLQuery("select height_centimeters from JPerson where name='Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
|
||||||
|
Double expiryViaSql = (Double)s.createSQLQuery("select pwd_expiry_weeks from JEmployee where person_id=?")
|
||||||
|
.setLong(0, e.getId())
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_WEEKS, expiryViaSql, 0.01d);
|
||||||
|
|
||||||
|
// Test projection
|
||||||
|
Double heightViaHql = (Double)s.createQuery("select p.heightInches from Person p where p.name = 'Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, heightViaHql, 0.01d);
|
||||||
|
Double expiryViaHql = (Double)s.createQuery("select e.passwordExpiryDays from Employee e where e.name = 'Steve'").uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, expiryViaHql, 0.01d);
|
||||||
|
|
||||||
|
// Test restriction and entity load via criteria
|
||||||
|
p = (Person)s.createCriteria(Person.class)
|
||||||
|
.add(Restrictions.between("heightInches", HEIGHT_INCHES - 0.01d, HEIGHT_INCHES + 0.01d))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, p.getHeightInches(), 0.01d);
|
||||||
|
e = (Employee)s.createCriteria(Employee.class)
|
||||||
|
.add(Restrictions.between("passwordExpiryDays", PASSWORD_EXPIRY_DAYS - 0.01d, PASSWORD_EXPIRY_DAYS + 0.01d))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, e.getPasswordExpiryDays(), 0.01d);
|
||||||
|
|
||||||
|
// Test predicate and entity load via HQL
|
||||||
|
p = (Person)s.createQuery("from Person p where p.heightInches between ? and ?")
|
||||||
|
.setDouble(0, HEIGHT_INCHES - 0.01d)
|
||||||
|
.setDouble(1, HEIGHT_INCHES + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, p.getHeightInches(), 0.01d);
|
||||||
|
e = (Employee)s.createQuery("from Employee e where e.passwordExpiryDays between ? and ?")
|
||||||
|
.setDouble(0, PASSWORD_EXPIRY_DAYS - 0.01d)
|
||||||
|
.setDouble(1, PASSWORD_EXPIRY_DAYS + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, e.getPasswordExpiryDays(), 0.01d);
|
||||||
|
|
||||||
|
// Test update
|
||||||
|
p.setHeightInches(1);
|
||||||
|
e.setPasswordExpiryDays(7);
|
||||||
|
s.flush();
|
||||||
|
heightViaSql = (Double)s.createSQLQuery("select height_centimeters from JPerson where name='Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(2.54d, heightViaSql, 0.01d);
|
||||||
|
expiryViaSql = (Double)s.createSQLQuery("select pwd_expiry_weeks from JEmployee where person_id=?")
|
||||||
|
.setLong(0, e.getId())
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(1d, expiryViaSql, 0.01d);
|
||||||
|
s.delete(p);
|
||||||
|
s.delete(e);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void testLockingJoinedSubclass() {
|
public void testLockingJoinedSubclass() {
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
|
@ -35,6 +35,12 @@
|
|||||||
<property name="sex"
|
<property name="sex"
|
||||||
not-null="true"
|
not-null="true"
|
||||||
update="false"/>
|
update="false"/>
|
||||||
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"
|
||||||
|
write="? * 2.54"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
<component name="address">
|
<component name="address">
|
||||||
<property name="address"/>
|
<property name="address"/>
|
||||||
@ -49,6 +55,12 @@
|
|||||||
length="20"/>
|
length="20"/>
|
||||||
<property name="salary"
|
<property name="salary"
|
||||||
length="0"/>
|
length="0"/>
|
||||||
|
<property name="passwordExpiryDays">
|
||||||
|
<column name="pwd_expiry_weeks"
|
||||||
|
not-null="true"
|
||||||
|
read="pwd_expiry_weeks * 7.0"
|
||||||
|
write="? / 7.0"/>
|
||||||
|
</property>
|
||||||
<many-to-one name="manager"/>
|
<many-to-one name="manager"/>
|
||||||
</joined-subclass>
|
</joined-subclass>
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ public class Person {
|
|||||||
private String name;
|
private String name;
|
||||||
private char sex;
|
private char sex;
|
||||||
private int version;
|
private int version;
|
||||||
|
private double heightInches;
|
||||||
private Address address = new Address();
|
private Address address = new Address();
|
||||||
/**
|
/**
|
||||||
* @return Returns the address.
|
* @return Returns the address.
|
||||||
@ -68,6 +69,20 @@ public void setName(String identity) {
|
|||||||
this.name = identity;
|
this.name = identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the height in inches.
|
||||||
|
*/
|
||||||
|
public double getHeightInches() {
|
||||||
|
return heightInches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param heightInches The height in inches to set.
|
||||||
|
*/
|
||||||
|
public void setHeightInches(double heightInches) {
|
||||||
|
this.heightInches = heightInches;
|
||||||
|
}
|
||||||
|
|
||||||
public int getVersion() {
|
public int getVersion() {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ public class Alien {
|
|||||||
private String identity;
|
private String identity;
|
||||||
private String planet;
|
private String planet;
|
||||||
private String species;
|
private String species;
|
||||||
|
private double heightInches;
|
||||||
|
|
||||||
public void setIdentity(String identity) {
|
public void setIdentity(String identity) {
|
||||||
this.identity = identity;
|
this.identity = identity;
|
||||||
@ -28,6 +29,12 @@ public void setPlanet(String planet) {
|
|||||||
public String getPlanet() {
|
public String getPlanet() {
|
||||||
return planet;
|
return planet;
|
||||||
}
|
}
|
||||||
|
public double getHeightInches() {
|
||||||
|
return heightInches;
|
||||||
|
}
|
||||||
|
public void setHeightInches(double heightInches) {
|
||||||
|
this.heightInches = heightInches;
|
||||||
|
}
|
||||||
public void setId(Long id) {
|
public void setId(Long id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ public class Being {
|
|||||||
private String identity;
|
private String identity;
|
||||||
private String location;
|
private String location;
|
||||||
private String species;
|
private String species;
|
||||||
|
private double heightInches;
|
||||||
|
|
||||||
public void setLocation(String location) {
|
public void setLocation(String location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
@ -28,4 +29,10 @@ public void setIdentity(String identity) {
|
|||||||
public String getIdentity() {
|
public String getIdentity() {
|
||||||
return identity;
|
return identity;
|
||||||
}
|
}
|
||||||
|
public double getHeightInches() {
|
||||||
|
return heightInches;
|
||||||
|
}
|
||||||
|
public void setHeightInches(double heightInches) {
|
||||||
|
this.heightInches = heightInches;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,12 @@
|
|||||||
not-null="true"
|
not-null="true"
|
||||||
update="false"/>
|
update="false"/>
|
||||||
<property name="address"/>
|
<property name="address"/>
|
||||||
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"
|
||||||
|
write="? * 2.54"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
@ -53,16 +59,22 @@
|
|||||||
<property name="species"
|
<property name="species"
|
||||||
not-null="true"
|
not-null="true"
|
||||||
update="false"/>
|
update="false"/>
|
||||||
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"
|
||||||
|
write="? * 2.54"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
<class name="Being" mutable="false">
|
<class name="Being" mutable="false">
|
||||||
|
|
||||||
<subselect>
|
<subselect>
|
||||||
select bid, name as ident, address as loc, 'human' as species
|
select bid, name as ident, address as loc, 'human' as species, height_centimeters
|
||||||
from humans
|
from humans
|
||||||
union
|
union
|
||||||
select bid, ident, planet as loc, species
|
select bid, ident, planet as loc, species, height_centimeters
|
||||||
from aliens
|
from aliens
|
||||||
</subselect>
|
</subselect>
|
||||||
|
|
||||||
@ -77,6 +89,11 @@
|
|||||||
<property name="identity" column="ident"/>
|
<property name="identity" column="ident"/>
|
||||||
<property name="location" column="loc"/>
|
<property name="location" column="loc"/>
|
||||||
<property name="species"/>
|
<property name="species"/>
|
||||||
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ public class Human {
|
|||||||
private String name;
|
private String name;
|
||||||
private char sex;
|
private char sex;
|
||||||
private String address;
|
private String address;
|
||||||
|
private double heightInches;
|
||||||
|
|
||||||
public void setAddress(String address) {
|
public void setAddress(String address) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
@ -34,4 +35,10 @@ public void setId(Long id) {
|
|||||||
public Long getId() {
|
public Long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
public double getHeightInches() {
|
||||||
|
return heightInches;
|
||||||
|
}
|
||||||
|
public void setHeightInches(double heightInches) {
|
||||||
|
this.heightInches = heightInches;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
|
|
||||||
@ -67,6 +68,57 @@ public void testEntitySubselect() {
|
|||||||
t.commit();
|
t.commit();
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
final double HUMAN_INCHES = 73;
|
||||||
|
final double ALIEN_INCHES = 931;
|
||||||
|
final double HUMAN_CENTIMETERS = HUMAN_INCHES * 2.54d;
|
||||||
|
final double ALIEN_CENTIMETERS = ALIEN_INCHES * 2.54d;
|
||||||
|
Human gavin = new Human();
|
||||||
|
gavin.setName( "gavin" );
|
||||||
|
gavin.setSex( 'M' );
|
||||||
|
gavin.setAddress( "Melbourne, Australia" );
|
||||||
|
gavin.setHeightInches( HUMAN_INCHES );
|
||||||
|
Alien x23y4 = new Alien();
|
||||||
|
x23y4.setIdentity( "x23y4$$hu%3" );
|
||||||
|
x23y4.setPlanet( "Mars" );
|
||||||
|
x23y4.setSpecies( "martian" );
|
||||||
|
x23y4.setHeightInches( ALIEN_INCHES );
|
||||||
|
s.save(gavin);
|
||||||
|
s.save(x23y4);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Test value conversion during insert
|
||||||
|
Double humanHeightViaSql = (Double)s.createSQLQuery("select height_centimeters from humans").uniqueResult();
|
||||||
|
assertEquals(HUMAN_CENTIMETERS, humanHeightViaSql, 0.01d);
|
||||||
|
Double alienHeightViaSql = (Double)s.createSQLQuery("select height_centimeters from aliens").uniqueResult();
|
||||||
|
assertEquals(ALIEN_CENTIMETERS, alienHeightViaSql, 0.01d);
|
||||||
|
s.clear();
|
||||||
|
|
||||||
|
// Test projection
|
||||||
|
Double heightViaHql = (Double)s.createQuery("select heightInches from Being b where b.identity = 'gavin'").uniqueResult();
|
||||||
|
assertEquals(HUMAN_INCHES, heightViaHql, 0.01d);
|
||||||
|
|
||||||
|
// Test restriction and entity load via criteria
|
||||||
|
Being b = (Being)s.createCriteria(Being.class)
|
||||||
|
.add(Restrictions.between("heightInches", HUMAN_INCHES - 0.01d, HUMAN_INCHES + 0.01d))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HUMAN_INCHES, b.getHeightInches(), 0.01d);
|
||||||
|
|
||||||
|
// Test predicate and entity load via HQL
|
||||||
|
b = (Being)s.createQuery("from Being b where b.heightInches between ? and ?")
|
||||||
|
.setDouble(0, ALIEN_INCHES - 0.01d)
|
||||||
|
.setDouble(1, ALIEN_INCHES + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(ALIEN_INCHES, b.getHeightInches(), 0.01d);
|
||||||
|
s.delete(gavin);
|
||||||
|
s.delete(x23y4);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
public class Employee extends Person {
|
public class Employee extends Person {
|
||||||
private String title;
|
private String title;
|
||||||
private BigDecimal salary;
|
private BigDecimal salary;
|
||||||
|
private double passwordExpiryDays;
|
||||||
private Employee manager;
|
private Employee manager;
|
||||||
/**
|
/**
|
||||||
* @return Returns the title.
|
* @return Returns the title.
|
||||||
@ -46,4 +47,16 @@ public BigDecimal getSalary() {
|
|||||||
public void setSalary(BigDecimal salary) {
|
public void setSalary(BigDecimal salary) {
|
||||||
this.salary = salary;
|
this.salary = salary;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return The password expiry policy in days.
|
||||||
|
*/
|
||||||
|
public double getPasswordExpiryDays() {
|
||||||
|
return passwordExpiryDays;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param passwordExpiryDays The password expiry policy in days.
|
||||||
|
*/
|
||||||
|
public void setPasswordExpiryDays(double passwordExpiryDays) {
|
||||||
|
this.passwordExpiryDays = passwordExpiryDays;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,12 @@
|
|||||||
<property name="sex"
|
<property name="sex"
|
||||||
not-null="true"
|
not-null="true"
|
||||||
update="false"/>
|
update="false"/>
|
||||||
|
<property name="heightInches">
|
||||||
|
<column name="height_centimeters"
|
||||||
|
not-null="true"
|
||||||
|
read="height_centimeters / 2.54"
|
||||||
|
write="? * 2.54"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
<component name="address">
|
<component name="address">
|
||||||
<property name="address" index="AddressIndex"/>
|
<property name="address" index="AddressIndex"/>
|
||||||
@ -47,6 +53,12 @@
|
|||||||
length="20"/>
|
length="20"/>
|
||||||
<property name="salary"
|
<property name="salary"
|
||||||
length="0"/>
|
length="0"/>
|
||||||
|
<property name="passwordExpiryDays">
|
||||||
|
<column name="pwd_expiry_weeks"
|
||||||
|
not-null="true"
|
||||||
|
read="pwd_expiry_weeks * 7.0"
|
||||||
|
write="? / 7.0"/>
|
||||||
|
</property>
|
||||||
<many-to-one name="manager"/>
|
<many-to-one name="manager"/>
|
||||||
</union-subclass>
|
</union-subclass>
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ public class Person {
|
|||||||
private long id;
|
private long id;
|
||||||
private String name;
|
private String name;
|
||||||
private char sex;
|
private char sex;
|
||||||
|
private double heightInches;
|
||||||
private Address address = new Address();
|
private Address address = new Address();
|
||||||
/**
|
/**
|
||||||
* @return Returns the address.
|
* @return Returns the address.
|
||||||
@ -66,5 +67,16 @@ public String getName() {
|
|||||||
public void setName(String identity) {
|
public void setName(String identity) {
|
||||||
this.name = identity;
|
this.name = identity;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return Returns the height in inches.
|
||||||
|
*/
|
||||||
|
public double getHeightInches() {
|
||||||
|
return heightInches;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param heightInches The height in inches to set.
|
||||||
|
*/
|
||||||
|
public void setHeightInches(double heightInches) {
|
||||||
|
this.heightInches = heightInches;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,5 +149,79 @@ public void testQuerySubclassAttribute() {
|
|||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCustomColumnReadAndWrite() {
|
||||||
|
Session s = openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
final double HEIGHT_INCHES = 73;
|
||||||
|
final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d;
|
||||||
|
Person p = new Person();
|
||||||
|
p.setName("Emmanuel");
|
||||||
|
p.setSex('M');
|
||||||
|
p.setHeightInches(HEIGHT_INCHES);
|
||||||
|
s.persist(p);
|
||||||
|
final double PASSWORD_EXPIRY_WEEKS = 4;
|
||||||
|
final double PASSWORD_EXPIRY_DAYS = PASSWORD_EXPIRY_WEEKS * 7d;
|
||||||
|
Employee e = new Employee();
|
||||||
|
e.setName("Steve");
|
||||||
|
e.setSex('M');
|
||||||
|
e.setTitle("Mr");
|
||||||
|
e.setPasswordExpiryDays(PASSWORD_EXPIRY_DAYS);
|
||||||
|
s.persist(e);
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
// Test value conversion during insert
|
||||||
|
Double heightViaSql = (Double)s.createSQLQuery("select height_centimeters from UPerson where name='Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
|
||||||
|
Double expiryViaSql = (Double)s.createSQLQuery("select pwd_expiry_weeks from UEmployee where person_id=?")
|
||||||
|
.setLong(0, e.getId())
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_WEEKS, expiryViaSql, 0.01d);
|
||||||
|
|
||||||
|
// Test projection
|
||||||
|
Double heightViaHql = (Double)s.createQuery("select p.heightInches from Person p where p.name = 'Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, heightViaHql, 0.01d);
|
||||||
|
Double expiryViaHql = (Double)s.createQuery("select e.passwordExpiryDays from Employee e where e.name = 'Steve'").uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, expiryViaHql, 0.01d);
|
||||||
|
|
||||||
|
// Test restriction and entity load via criteria
|
||||||
|
p = (Person)s.createCriteria(Person.class)
|
||||||
|
.add(Restrictions.between("heightInches", HEIGHT_INCHES - 0.01d, HEIGHT_INCHES + 0.01d))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, p.getHeightInches(), 0.01d);
|
||||||
|
e = (Employee)s.createCriteria(Employee.class)
|
||||||
|
.add(Restrictions.between("passwordExpiryDays", PASSWORD_EXPIRY_DAYS - 0.01d, PASSWORD_EXPIRY_DAYS + 0.01d))
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, e.getPasswordExpiryDays(), 0.01d);
|
||||||
|
|
||||||
|
// Test predicate and entity load via HQL
|
||||||
|
p = (Person)s.createQuery("from Person p where p.heightInches between ? and ?")
|
||||||
|
.setDouble(0, HEIGHT_INCHES - 0.01d)
|
||||||
|
.setDouble(1, HEIGHT_INCHES + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(HEIGHT_INCHES, p.getHeightInches(), 0.01d);
|
||||||
|
e = (Employee)s.createQuery("from Employee e where e.passwordExpiryDays between ? and ?")
|
||||||
|
.setDouble(0, PASSWORD_EXPIRY_DAYS - 0.01d)
|
||||||
|
.setDouble(1, PASSWORD_EXPIRY_DAYS + 0.01d)
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(PASSWORD_EXPIRY_DAYS, e.getPasswordExpiryDays(), 0.01d);
|
||||||
|
|
||||||
|
// Test update
|
||||||
|
p.setHeightInches(1);
|
||||||
|
e.setPasswordExpiryDays(7);
|
||||||
|
s.flush();
|
||||||
|
heightViaSql = (Double)s.createSQLQuery("select height_centimeters from UPerson where name='Emmanuel'").uniqueResult();
|
||||||
|
assertEquals(2.54d, heightViaSql, 0.01d);
|
||||||
|
expiryViaSql = (Double)s.createSQLQuery("select pwd_expiry_weeks from UEmployee where person_id=?")
|
||||||
|
.setLong(0, e.getId())
|
||||||
|
.uniqueResult();
|
||||||
|
assertEquals(1d, expiryViaSql, 0.01d);
|
||||||
|
s.delete(p);
|
||||||
|
s.delete(e);
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user