下面列出了怎么用org.hibernate.dialect.function.SQLFunction的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
@SuppressWarnings("SimplifiableIfStatement")
protected boolean isFunctionName(AST ast) {
/*
* Semantic predicate used to determine whether a given AST node represents a function call
*/
AST child = ast.getFirstChild();
// assume it is a function if it has parameters
if ( child != null && "{param list}".equals( child.getText() ) ) {
return true;
}
// otherwise, in order for this to be a function logically it has to be a function that does not
// have arguments. So try to assert that using the registry of known functions
final SQLFunction function = context.getSqlFunctionRegistry().findSQLFunction( ast.getText() );
if ( function == null ) {
// no registered function, so we cannot know for certain
return false;
}
else {
// if function.hasParenthesesIfNoArguments() is true, then assume the node is not a function
return !function.hasParenthesesIfNoArguments();
}
}
public InFlightMetadataCollectorImpl(
BootstrapContext bootstrapContext,
MetadataBuildingOptions options) {
this.bootstrapContext = bootstrapContext;
this.uuid = UUID.randomUUID();
this.options = options;
this.identifierGeneratorFactory = options.getServiceRegistry()
.getService( MutableIdentifierGeneratorFactory.class );
for ( Map.Entry<String, SQLFunction> sqlFunctionEntry : bootstrapContext.getSqlFunctions().entrySet() ) {
if ( sqlFunctionMap == null ) {
// we need this to be a ConcurrentHashMap for the one we ultimately pass along to the SF
// but is this the reference that gets passed along?
sqlFunctionMap = new ConcurrentHashMap<>( 16, .75f, 1 );
}
sqlFunctionMap.put( sqlFunctionEntry.getKey(), sqlFunctionEntry.getValue() );
}
bootstrapContext.getAuxiliaryDatabaseObjectList().forEach( getDatabase()::addAuxiliaryDatabaseObject );
}
@Override
public Type getDataType() {
Type type = super.getDataType();
if ( type != null ) {
return type;
}
FromElement fe = getFromElement();
if ( fe != null ) {
return fe.getDataType();
}
SQLFunction sf = getWalker().getSessionFactoryHelper().findSQLFunction( getText() );
if ( sf != null ) {
return sf.getReturnType( null, getWalker().getSessionFactoryHelper().getFactory() );
}
return null;
}
@Override
protected void beginFunctionTemplate(AST node, AST nameNode) {
// NOTE for AGGREGATE both nodes are the same; for METHOD the first is the METHOD, the second is the
// METHOD_NAME
FunctionNode functionNode = (FunctionNode) node;
SQLFunction sqlFunction = functionNode.getSQLFunction();
if ( sqlFunction == null ) {
// if SQLFunction is null we just write the function out as it appears in the hql statement
super.beginFunctionTemplate( node, nameNode );
}
else {
// this function has a registered SQLFunction -> redirect output and catch the arguments
outputStack.addFirst( writer );
if ( node.getType() == CAST ) {
writer = new CastFunctionArguments();
}
else {
writer = new StandardFunctionArguments();
}
}
}
/**
* Find the function return type given the function name and the first argument expression node.
*
* @param functionName The function name.
* @param first The first argument expression.
* @return the function return type given the function name and the first argument expression node.
*/
public Type findFunctionReturnType(String functionName, AST first) {
// locate the registered function by the given name
SQLFunction sqlFunction = requireSQLFunction( functionName );
// determine the type of the first argument...
Type argumentType = null;
if ( first != null ) {
if ( "cast".equals(functionName) ) {
argumentType = TypeFactory.heuristicType( first.getNextSibling().getText() );
}
else if ( first instanceof SqlNode ) {
argumentType = ( (SqlNode) first ).getDataType();
}
}
return sqlFunction.getReturnType( argumentType, sfi );
}
public void afterConfigurationBuilt(Mappings mappings, Dialect dialect) {
super.afterConfigurationBuilt( mappings, dialect );
// Oracle and Postgres do not have year() functions, so we need to
// redefine the 'User.person.yob' formula
//
// consider temporary until we add the capability to define
// mapping foprmulas which can use dialect-registered functions...
PersistentClass user = mappings.getClass( User.class.getName() );
org.hibernate.mapping.Property personProperty = user.getProperty( "person" );
Component component = ( Component ) personProperty.getValue();
Formula f = ( Formula ) component.getProperty( "yob" ).getValue().getColumnIterator().next();
SQLFunction yearFunction = ( SQLFunction ) dialect.getFunctions().get( "year" );
if ( yearFunction == null ) {
// the dialect not know to support a year() function, so rely on the
// ANSI SQL extract function
f.setFormula( "extract( year from dob )");
}
else {
List args = new ArrayList();
args.add( "dob" );
f.setFormula( yearFunction.render( args, null ) );
}
}
protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
final SQLFunctionRegistry sqlFunctionRegistry = criteriaQuery.getFactory().getSqlFunctionRegistry();
final SQLFunction function = sqlFunctionRegistry.findSQLFunction( "count" );
if ( function == null ) {
throw new HibernateException( "Unable to locate count function mapping" );
}
return function;
}
protected SQLFunction getFunction(String functionName, CriteriaQuery criteriaQuery) {
final SQLFunction function = criteriaQuery.getFactory()
.getSqlFunctionRegistry()
.findSQLFunction( functionName );
if ( function == null ) {
throw new HibernateException( "Unable to locate mapping for function named [" + functionName + "]" );
}
return function;
}
/**
* Same functionality as {@link #renderWhereStringTemplate(String, String, Dialect, SQLFunctionRegistry)},
* except that a SQLFunctionRegistry is not provided (i.e., only the dialect-defined functions are
* considered). This is only intended for use by the annotations project until the
* many-to-many/map-key-from-target-table feature is pulled into core.
*
* @deprecated Only intended for annotations usage; use {@link #renderWhereStringTemplate(String, String, Dialect, SQLFunctionRegistry)} instead
*/
@Deprecated
@SuppressWarnings({ "JavaDoc" })
public static String renderWhereStringTemplate(String sqlWhereString, String placeholder, Dialect dialect) {
return renderWhereStringTemplate(
sqlWhereString,
placeholder,
dialect,
new SQLFunctionRegistry( dialect, java.util.Collections.<String, SQLFunction>emptyMap() )
);
}
private static boolean isFunction(String lcToken, String nextToken, SQLFunctionRegistry functionRegistry) {
// checking for "(" is currently redundant because it is checked before getting here;
// doing the check anyhow, in case that earlier check goes away;
if ( "(".equals( nextToken ) ) {
return true;
}
SQLFunction function = functionRegistry.findSQLFunction(lcToken);
if ( function == null ) {
// lcToken does not refer to a function
return false;
}
// if function.hasParenthesesIfNoArguments() is true, then assume
// lcToken is not a function (since it is not followed by '(')
return ! function.hasParenthesesIfNoArguments();
}
@Override
public T applySqlFunction(
String registrationName,
SQLFunction sqlFunction) {
delegate.applySqlFunction( registrationName, sqlFunction );
return getThis();
}
public SessionFactoryBuilderImpl(MetadataImplementor metadata, BootstrapContext bootstrapContext) {
this.metadata = metadata;
this.bootstrapContext = bootstrapContext;
this.optionsBuilder = new SessionFactoryOptionsBuilder(
metadata.getMetadataBuildingOptions().getServiceRegistry(),
bootstrapContext
);
if ( metadata.getSqlFunctionMap() != null ) {
for ( Map.Entry<String, SQLFunction> sqlFunctionEntry : metadata.getSqlFunctionMap().entrySet() ) {
applySqlFunction( sqlFunctionEntry.getKey(), sqlFunctionEntry.getValue() );
}
}
}
@Override
protected void endFunctionTemplate(AST node) {
FunctionNode functionNode = (FunctionNode) node;
SQLFunction sqlFunction = functionNode.getSQLFunction();
if ( sqlFunction == null ) {
super.endFunctionTemplate( node );
}
else {
final Type functionType = functionNode.getFirstArgumentType();
// this function has a registered SQLFunction -> redirect output and catch the arguments
FunctionArgumentsCollectingWriter functionArguments = (FunctionArgumentsCollectingWriter) writer;
writer = outputStack.removeFirst();
out( sqlFunction.render( functionType, functionArguments.getArgs(), sessionFactory ) );
}
}
public Type findFunctionReturnType(String functionName, SQLFunction sqlFunction, AST firstArgument) {
// determine the type of the first argument...
Type argumentType = null;
if ( firstArgument != null ) {
if ( "cast".equals( functionName ) ) {
argumentType = sfi.getTypeResolver().heuristicType( firstArgument.getNextSibling().getText() );
}
else if ( SqlNode.class.isInstance( firstArgument ) ) {
argumentType = ( (SqlNode) firstArgument ).getDataType();
}
}
return sqlFunction.getReturnType( argumentType, sfi );
}
public Type getDataType() {
Type type = super.getDataType();
if (type != null) return type;
FromElement fe = getFromElement();
if (fe != null) return fe.getDataType();
SQLFunction sf = getWalker().getSessionFactoryHelper().findSQLFunction(getText());
return sf == null ? null : sf.getReturnType(null, null);
}
protected void beginFunctionTemplate(AST m, AST i) {
MethodNode methodNode = ( MethodNode ) m;
SQLFunction template = methodNode.getSQLFunction();
if ( template == null ) {
// if template is null we just write the function out as it appears in the hql statement
super.beginFunctionTemplate( m, i );
}
else {
// this function has a template -> redirect output and catch the arguments
outputStack.addFirst( writer );
writer = new FunctionArguments();
}
}
protected void endFunctionTemplate(AST m) {
MethodNode methodNode = ( MethodNode ) m;
SQLFunction template = methodNode.getSQLFunction();
if ( template == null ) {
super.endFunctionTemplate( m );
}
else {
// this function has a template -> restore output, apply the template and write the result out
FunctionArguments functionArguments = ( FunctionArguments ) writer; // TODO: Downcast to avoid using an interface? Yuck.
writer = ( SqlWriter ) outputStack.removeFirst();
out( template.render( functionArguments.getArgs(), sessionFactory ) );
}
}
/**
* Locate a registered sql function by name, requiring that such a registered function exist.
*
* @param functionName The name of the function to locate
* @return The sql function.
* @throws QueryException Indicates no matching sql functions could be found.
*/
private SQLFunction requireSQLFunction(String functionName) {
SQLFunction f = findSQLFunction( functionName );
if ( f == null ) {
throw new QueryException( "Unable to find SQL function: " + functionName );
}
return f;
}
private String locateAppropriateDialectFunctionNameForAliasTest() {
for (Iterator itr = getDialect().getFunctions().entrySet().iterator(); itr.hasNext(); ) {
final Map.Entry entry = (Map.Entry) itr.next();
final SQLFunction function = (SQLFunction) entry.getValue();
if ( !function.hasArguments() && !function.hasParenthesesIfNoArguments() ) {
return (String) entry.getKey();
}
}
return null;
}
public void afterConfigurationBuilt(Mappings mappings, Dialect dialect) {
super.afterConfigurationBuilt( mappings, dialect );
Collection children = mappings.getCollection( Parent.class.getName() + ".children" );
Component childComponents = ( Component ) children.getElement();
Formula f = ( Formula ) childComponents.getProperty( "bioLength" ).getValue().getColumnIterator().next();
SQLFunction lengthFunction = ( SQLFunction ) dialect.getFunctions().get( "length" );
if ( lengthFunction != null ) {
ArrayList args = new ArrayList();
args.add( "bio" );
f.setFormula( lengthFunction.render( args, null ) );
}
}
private String locateAppropriateDialectFunctionNameForAliasTest() {
for (Iterator itr = getDialect().getFunctions().entrySet().iterator(); itr.hasNext(); ) {
final Map.Entry entry = (Map.Entry) itr.next();
final SQLFunction function = (SQLFunction) entry.getValue();
if ( !function.hasArguments() && !function.hasParenthesesIfNoArguments() ) {
return (String) entry.getKey();
}
}
return null;
}
public void testExpressionInFunction() throws Exception {
assertTranslation( "from Animal an where an.bodyWeight > abs(3-5)" );
assertTranslation( "from Animal an where an.bodyWeight > abs(3/5)" );
assertTranslation( "from Animal an where an.bodyWeight > abs(3+5)" );
assertTranslation( "from Animal an where an.bodyWeight > abs(3*5)" );
SQLFunction concat = getSessionFactoryImplementor().getSqlFunctionRegistry().findSQLFunction( "concat");
List list = new ArrayList(); list.add("'fat'"); list.add("'skinny'");
assertTranslation( "from Animal an where an.description = " + concat.render(list, getSessionFactoryImplementor()) );
}
public SQLiteDialect() {
registerColumnType(Types.BIT, "boolean");
registerColumnType(Types.TINYINT, "tinyint");
registerColumnType(Types.SMALLINT, "smallint");
registerColumnType(Types.INTEGER, "integer");
registerColumnType(Types.BIGINT, "bigint");
registerColumnType(Types.FLOAT, "float");
registerColumnType(Types.REAL, "real");
registerColumnType(Types.DOUBLE, "double");
registerColumnType(Types.NUMERIC, "numeric($p, $s)");
registerColumnType(Types.DECIMAL, "decimal");
registerColumnType(Types.CHAR, "char");
registerColumnType(Types.VARCHAR, "varchar($l)");
registerColumnType(Types.LONGVARCHAR, "longvarchar");
registerColumnType(Types.DATE, "date");
registerColumnType(Types.TIME, "time");
registerColumnType(Types.TIMESTAMP, "datetime");
registerColumnType(Types.BINARY, "blob");
registerColumnType(Types.VARBINARY, "blob");
registerColumnType(Types.LONGVARBINARY, "blob");
registerColumnType(Types.BLOB, "blob");
registerColumnType(Types.CLOB, "clob");
registerColumnType(Types.BOOLEAN, "boolean");
//registerFunction( "abs", new StandardSQLFunction("abs") );
registerFunction( "concat", new VarArgsSQLFunction(StandardBasicTypes.STRING, "", "||", "") );
//registerFunction( "length", new StandardSQLFunction("length", StandardBasicTypes.LONG) );
//registerFunction( "lower", new StandardSQLFunction("lower") );
registerFunction( "mod", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "?1 % ?2" ) );
registerFunction( "quote", new StandardSQLFunction("quote", StandardBasicTypes.STRING) );
registerFunction( "random", new NoArgSQLFunction("random", StandardBasicTypes.INTEGER) );
registerFunction( "round", new StandardSQLFunction("round") );
registerFunction( "substr", new StandardSQLFunction("substr", StandardBasicTypes.STRING) );
registerFunction( "substring", new SQLFunctionTemplate( StandardBasicTypes.STRING, "substr(?1, ?2, ?3)" ) );
registerFunction( "trim", new AbstractAnsiTrimEmulationFunction() {
protected SQLFunction resolveBothSpaceTrimFunction() {
return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1)");
}
protected SQLFunction resolveBothSpaceTrimFromFunction() {
return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?2)");
}
protected SQLFunction resolveLeadingSpaceTrimFunction() {
return new SQLFunctionTemplate(StandardBasicTypes.STRING, "ltrim(?1)");
}
protected SQLFunction resolveTrailingSpaceTrimFunction() {
return new SQLFunctionTemplate(StandardBasicTypes.STRING, "rtrim(?1)");
}
protected SQLFunction resolveBothTrimFunction() {
return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1, ?2)");
}
protected SQLFunction resolveLeadingTrimFunction() {
return new SQLFunctionTemplate(StandardBasicTypes.STRING, "ltrim(?1, ?2)");
}
protected SQLFunction resolveTrailingTrimFunction() {
return new SQLFunctionTemplate(StandardBasicTypes.STRING, "rtrim(?1, ?2)");
}
} );
//registerFunction( "upper", new StandardSQLFunction("upper") );
}
@Override
public Map<String, SQLFunction> getSqlFunctionMap() {
return metadata.getSqlFunctionMap();
}
/**
* Create a {@link SessionFactory} using the properties and mappings in this configuration. The
* SessionFactory will be immutable, so changes made to this Configuration after building the
* SessionFactory will not affect it.
*
* @param serviceRegistry The registry of services to be used in creating this session factory.
*
* @return The built {@link SessionFactory}
*
* @throws HibernateException usually indicates an invalid configuration or invalid mapping information
*/
public SessionFactory buildSessionFactory(ServiceRegistry serviceRegistry) throws HibernateException {
log.debug( "Building session factory using provided StandardServiceRegistry" );
final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder( (StandardServiceRegistry) serviceRegistry );
if ( implicitNamingStrategy != null ) {
metadataBuilder.applyImplicitNamingStrategy( implicitNamingStrategy );
}
if ( physicalNamingStrategy != null ) {
metadataBuilder.applyPhysicalNamingStrategy( physicalNamingStrategy );
}
if ( sharedCacheMode != null ) {
metadataBuilder.applySharedCacheMode( sharedCacheMode );
}
if ( !typeContributorRegistrations.isEmpty() ) {
for ( TypeContributor typeContributor : typeContributorRegistrations ) {
metadataBuilder.applyTypes( typeContributor );
}
}
if ( !basicTypes.isEmpty() ) {
for ( BasicType basicType : basicTypes ) {
metadataBuilder.applyBasicType( basicType );
}
}
if ( sqlFunctions != null ) {
for ( Map.Entry<String, SQLFunction> entry : sqlFunctions.entrySet() ) {
metadataBuilder.applySqlFunction( entry.getKey(), entry.getValue() );
}
}
if ( auxiliaryDatabaseObjectList != null ) {
for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : auxiliaryDatabaseObjectList ) {
metadataBuilder.applyAuxiliaryDatabaseObject( auxiliaryDatabaseObject );
}
}
if ( attributeConverterDefinitionsByClass != null ) {
for ( AttributeConverterDefinition attributeConverterDefinition : attributeConverterDefinitionsByClass.values() ) {
metadataBuilder.applyAttributeConverter( attributeConverterDefinition );
}
}
final Metadata metadata = metadataBuilder.build();
final SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder();
if ( interceptor != null && interceptor != EmptyInterceptor.INSTANCE ) {
sessionFactoryBuilder.applyInterceptor( interceptor );
}
if ( getSessionFactoryObserver() != null ) {
sessionFactoryBuilder.addSessionFactoryObservers( getSessionFactoryObserver() );
}
if ( getEntityNotFoundDelegate() != null ) {
sessionFactoryBuilder.applyEntityNotFoundDelegate( getEntityNotFoundDelegate() );
}
if ( getEntityTuplizerFactory() != null ) {
sessionFactoryBuilder.applyEntityTuplizerFactory( getEntityTuplizerFactory() );
}
if ( getCurrentTenantIdentifierResolver() != null ) {
sessionFactoryBuilder.applyCurrentTenantIdentifierResolver( getCurrentTenantIdentifierResolver() );
}
return sessionFactoryBuilder.build();
}
public Map<String,SQLFunction> getSqlFunctions() {
return sqlFunctions;
}
public void addSqlFunction(String functionName, SQLFunction function) {
if ( sqlFunctions == null ) {
sqlFunctions = new HashMap<String, SQLFunction>();
}
sqlFunctions.put( functionName, function );
}
protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
return getFunction( getFunctionName(), criteriaQuery );
}
public MySQL57Dialect() {
super();
// For details about MySQL 5.7 support for fractional seconds
// precision (fsp): http://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html
// Regarding datetime(fsp), "The fsp value, if given, must be
// in the range 0 to 6. A value of 0 signifies that there is
// no fractional part. If omitted, the default precision is 0.
// (This differs from the standard SQL default of 6, for
// compatibility with previous MySQL versions.)".
// The following is defined because Hibernate currently expects
// the SQL 1992 default of 6 (which is inconsistent with the MySQL
// default).
registerColumnType( Types.TIMESTAMP, "datetime(6)" );
// MySQL 5.7 brings JSON native support with a dedicated datatype.
// For more details about MySql new JSON datatype support, see:
// https://dev.mysql.com/doc/refman/5.7/en/json.html
registerColumnType( Types.JAVA_OBJECT, "json" );
// MySQL also supports fractional seconds precision for time values
// (time(fsp)). According to SQL 1992, the default for <time precision>
// is 0. The MySQL default is time(0), there's no need to override
// the setting for Types.TIME columns.
// For details about MySQL support for timestamp functions, see:
// http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html
// The following are synonyms for now(fsp), where fsp defaults to 0 on MySQL 5.7:
// current_timestamp([fsp]), localtime(fsp), localtimestamp(fsp).
// Register the same StaticPrecisionFspTimestampFunction for all 4 functions.
final SQLFunction currentTimestampFunction = new StaticPrecisionFspTimestampFunction("now", 6 );
registerFunction( "now", currentTimestampFunction );
registerFunction( "current_timestamp", currentTimestampFunction );
registerFunction( "localtime", currentTimestampFunction );
registerFunction( "localtimestamp", currentTimestampFunction );
// sysdate is different from now():
// "SYSDATE() returns the time at which it executes. This differs
// from the behavior for NOW(), which returns a constant time that
// indicates the time at which the statement began to execute.
// (Within a stored function or trigger, NOW() returns the time at
// which the function or triggering statement began to execute.)
registerFunction( "sysdate", new StaticPrecisionFspTimestampFunction( "sysdate", 6 ) );
// from_unixtime(), timestamp() are functions that return TIMESTAMP that do not support a
// fractional seconds precision argument (so there's no need to override them here):
}
public MariaDB53Dialect() {
super();
// For details about MariaDB 5.3 support for fractional seconds
// precision (fsp): https://mariadb.com/kb/en/mariadb/microseconds-in-mariadb/
// Regarding datetime(fsp), "The fsp value, if given, must be
// in the range 0 to 6. A value of 0 signifies that there is
// no fractional part. If omitted, the default precision is 0.
// (This differs from the standard SQL default of 6, for
// compatibility with previous MariaDB versions.)".
// The following is defined because Hibernate currently expects
// the SQL 1992 default of 6 (which is inconsistent with the MariaDB
// default).
registerColumnType( Types.TIMESTAMP, "datetime(6)" );
// MariaDB also supports fractional seconds precision for time values
// (time(fsp)). According to SQL 1992, the default for <time precision>
// is 0. The MariaDB default is time(0), there's no need to override
// the setting for Types.TIME columns.
// For details about MariaDB support for timestamp functions, see:
// http://dev.MariaDB.com/doc/refman/5.7/en/date-and-time-functions.html
// The following are synonyms for now(fsp), where fsp defaults to 0 on MariaDB 5.3:
// current_timestamp([fsp]), localtime(fsp), localtimestamp(fsp).
// Register the same StaticPrecisionFspTimestampFunction for all 4 functions.
final SQLFunction currentTimestampFunction = new StaticPrecisionFspTimestampFunction( "now", 6 );
registerFunction( "now", currentTimestampFunction );
registerFunction( "current_timestamp", currentTimestampFunction );
registerFunction( "localtime", currentTimestampFunction );
registerFunction( "localtimestamp", currentTimestampFunction );
// sysdate is different from now():
// "SYSDATE() returns the time at which it executes. This differs
// from the behavior for NOW(), which returns a constant time that
// indicates the time at which the statement began to execute.
// (Within a stored function or trigger, NOW() returns the time at
// which the function or triggering statement began to execute.)
registerFunction( "sysdate", new StaticPrecisionFspTimestampFunction( "sysdate", 6 ) );
// from_unixtime(), timestamp() are functions that return TIMESTAMP that do not support a
// fractional seconds precision argument (so there's no need to override them here):
}