HHH-8844 - Add support for Java 8 date and time types (JSR-310)

This commit is contained in:
Steve Ebersole 2015-03-24 16:01:15 -05:00
parent 3e73948dae
commit 5f6d1d24f7
26 changed files with 1183 additions and 58 deletions

View File

@ -22,6 +22,7 @@ buildscript {
repositories {
mavenCentral()
mavenLocal()
jcenter()
maven {
name 'jboss-nexus'
@ -120,9 +121,6 @@ subprojects { subProject ->
// todo : need to make sure these are non-exported
description = 'Non-exported compile-time dependencies.'
}
jbossLoggingTool {
description = "Dependencies for running the JBoss logging AnnotationProcessor tool"
}
jaxb {
description = 'Dependencies for running ant xjc (jaxb class generation)'
}
@ -149,8 +147,6 @@ subprojects { subProject ->
testRuntime( libraries.h2 )
testRuntime( libraries.woodstox )
jbossLoggingTool( libraries.logging_processor )
jaxb( libraries.jaxb ){
exclude group: "javax.xml.stream"
}
@ -159,7 +155,6 @@ subprojects { subProject ->
jaxb( libraries.jaxb2_jaxb )
jaxb( libraries.jaxb2_jaxb_xjc )
animalSniffer ( libraries.animal_sniffer )
javaApiSignature ( libraries.java16_signature )
}
@ -273,32 +268,10 @@ subprojects { subProject ->
// Gradle plugin). For now, just compile first in order to get the logging classes.
eclipseClasspath.dependsOn generateSources
// Animal Sniffer ~~~~~~~~~~~~~~~~~~
// add animal sniffer Java API checking to the main compile tasks
// copy the resolved Animal Sniffer signature dependency artifact to a known location and name
task copyJavaApiSignature(type: Copy) {
from configurations.javaApiSignature
into "$buildDir/javaApiSignature/"
rename '.*signature', 'javaApi.signature'
}
// prepare the Animal Sniffer signature copy every time (before) we compile
compileJava.dependsOn copyJavaApiSignature
// and then after compilation, run the Animal Sniffer tool
compileJava.doLast {
ant.taskdef(
name: 'animalSniffer',
classname: 'org.codehaus.mojo.animal_sniffer.ant.CheckSignatureTask',
classpath: configurations.animalSniffer.asPath
)
ant.animalSniffer(
signature: "$buildDir/javaApiSignature/javaApi.signature",
classpath: sourceSets.main.compileClasspath.asPath) {
path( path: sourceSets.main.output.classesDir )
if ( subProject.name != 'hibernate-java8' ) {
apply plugin: org.hibernate.build.animalsniffer.AnimalSnifferPlugin
animalsniffer {
signature = "org.codehaus.mojo.signature:java16:+@signature"
}
}

12
buildSrc/build.gradle Normal file
View File

@ -0,0 +1,12 @@
repositories {
mavenCentral()
}
apply plugin: "groovy"
dependencies {
compile gradleApi()
compile localGroovy()
compile "org.codehaus.mojo:animal-sniffer:1.14"
}

View File

@ -0,0 +1,92 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.build.animalsniffer
import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.JavaPlugin
import groovy.transform.Canonical
import org.codehaus.mojo.animal_sniffer.SignatureChecker
import org.codehaus.mojo.animal_sniffer.logging.Logger
import org.slf4j.LoggerFactory
class AnimalSnifferPlugin implements Plugin<Project> {
private org.slf4j.Logger logger = LoggerFactory.getLogger( this.class )
@Override
void apply(Project project) {
project.configurations.maybeCreate( "signature" )
final AnimalSnifferExtension extension = project.extensions.create( "animalsniffer", AnimalSnifferExtension )
project.tasks.findByName( JavaPlugin.CLASSES_TASK_NAME ).doLast(
new Action<Task>() {
@Override
void execute(Task task) {
if ( extension.skip ) {
return;
}
def logger = new GradleLogger( logger )
def signatures = project.configurations.signature.resolvedConfiguration.resolvedArtifacts*.file
signatures.each {
SignatureChecker signatureChecker = new SignatureChecker(
it.newInputStream(),
Collections.emptySet(),
logger
)
signatureChecker.setCheckJars( false );
List<File> sourceDirs = new ArrayList<File>();
sourceDirs.addAll( task.project.sourceSets.main.java.srcDirs )
signatureChecker.setSourcePath( sourceDirs )
signatureChecker.process( project.file( task.project.sourceSets.main.output.classesDir ) );
if ( signatureChecker.isSignatureBroken() ) {
throw new GradleException(
"Signature errors found. Verify them and ignore them with the proper annotation if needed."
);
}
}
}
}
);
}
}
@Canonical
class GradleLogger implements Logger {
@Delegate
org.slf4j.Logger logger
}
class AnimalSnifferExtension {
String signature = ""
String[] signatures = []
boolean skip = false
}

View File

@ -33,7 +33,7 @@ import org.hibernate.internal.util.StringHelper;
*
* @author Steve Ebersole
*/
public class Identifier {
public class Identifier implements Comparable<Identifier> {
private final String text;
private final boolean isQuoted;
@ -211,5 +211,10 @@ public class Identifier {
? identifier
: Identifier.toIdentifier( identifier.getText(), true );
}
@Override
public int compareTo(Identifier o) {
return getCanonicalName().compareTo( o.getCanonicalName() );
}
}

View File

@ -26,9 +26,9 @@ package org.hibernate.boot.model.relational;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
@ -48,7 +48,7 @@ public class Database {
private Schema implicitSchema;
private final Map<Schema.Name,Schema> schemaMap = new HashMap<Schema.Name, Schema>();
private final Map<Schema.Name,Schema> schemaMap = new TreeMap<Schema.Name, Schema>();
private List<AuxiliaryDatabaseObject> auxiliaryDatabaseObjects;
private List<InitCommand> initCommands;

View File

@ -24,8 +24,8 @@
package org.hibernate.boot.model.relational;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import org.hibernate.HibernateException;
import org.hibernate.boot.model.naming.Identifier;
@ -48,8 +48,8 @@ public class Schema {
private final Name physicalName;
private Map<Identifier, Table> tables = new HashMap<Identifier, Table>();
private Map<Identifier, Sequence> sequences = new HashMap<Identifier, Sequence>();
private Map<Identifier, Table> tables = new TreeMap<Identifier, Table>();
private Map<Identifier, Sequence> sequences = new TreeMap<Identifier, Sequence>();
public Schema(Database database, Name name) {
this.database = database;
@ -168,7 +168,7 @@ public class Schema {
return sequences.values();
}
public static class Name {
public static class Name implements Comparable<Name> {
private final Identifier catalog;
private final Identifier schema;
@ -211,5 +211,38 @@ public class Schema {
result = 31 * result + (schema != null ? schema.hashCode() : 0);
return result;
}
@Override
public int compareTo(Name that) {
// per Comparable, the incoming Name cannot be null. However, its catalog/schema might be
// so we need to account for that.
int catalogCheck = ComparableHelper.compare( this.getCatalog(), that.getCatalog() );
if ( catalogCheck != 0 ) {
return catalogCheck;
}
return ComparableHelper.compare( this.getSchema(), that.getSchema() );
}
}
public static class ComparableHelper {
public static <T extends Comparable<T>> int compare(T first, T second) {
if ( first == null ) {
if ( second == null ) {
return 0;
}
else {
return 1;
}
}
else {
if ( second == null ) {
return -1;
}
else {
return first.compareTo( second );
}
}
}
}
}

View File

@ -33,7 +33,7 @@ import java.util.Comparator;
* @author Gavin King
* @author Steve Ebersole
*/
public class ComparableComparator implements Comparator<Comparable>, Serializable {
public class ComparableComparator<T extends Comparable> implements Comparator<T>, Serializable {
public static final Comparator INSTANCE = new ComparableComparator();
@SuppressWarnings({ "unchecked" })

View File

@ -22,7 +22,6 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.criteria;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
@ -36,12 +35,16 @@ import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TeradataDialect;
import org.hibernate.test.hql.StateProvince;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.hql.StateProvince;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* HHH-2166 Long "in" lists in queries results in a Java stack overflow
* exception. to reproduce this issue, you should add
@ -49,6 +52,7 @@ import org.junit.Test;
*
* @author Strong Liu
*/
@Ignore
public class LongInElementsTest extends BaseCoreFunctionalTestCase {
private static final int ELEMENTS_SIZE = 4000;

View File

@ -1,11 +1,5 @@
apply plugin: 'hibernate-matrix-testing'
configurations {
hibernateJpaModelGenTool {
description = "Dependencies for running the Hibernate JPA Metamodel Generator AnnotationProcessor tool"
}
}
dependencies {
compile( project( ':hibernate-core' ) )
compile( project( ':hibernate-entitymanager' ) )
@ -17,8 +11,6 @@ dependencies {
testCompile( project(path: ':hibernate-entitymanager', configuration: 'tests') )
testRuntime( libraries.javassist )
hibernateJpaModelGenTool( project( ':hibernate-jpamodelgen' ) )
}
def pomName() {
@ -48,8 +40,6 @@ sourceSets {
}
}
addMetaGenProcessor( sourceSets.main )
jar {
manifest {
instructionFirst 'Import-Package',

View File

@ -23,8 +23,7 @@
*/
package org.hibernate.envers.internal;
import org.hibernate.internal.CoreMessageLogger;
import org.jboss.logging.BasicLogger;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;
@ -38,7 +37,7 @@ import static org.jboss.logging.Logger.Level.WARN;
* New messages must be added after the last message defined to ensure message codes are unique.
*/
@MessageLogger(projectCode = "HHH")
public interface EnversMessageLogger extends CoreMessageLogger {
public interface EnversMessageLogger extends BasicLogger {
/**
* Message indicating that user attempted to use the deprecated ValidTimeAuditStrategy
*/

View File

@ -0,0 +1,28 @@
dependencies {
compile( project(':hibernate-core') )
testCompile( project(':hibernate-testing') )
}
targetCompatibility = '1.8'
sourceCompatibility = '1.8'
tasks.withType( JavaCompile.class ).all { task->
task.options.compilerArgs += [
"-nowarn",
"-encoding", "UTF-8",
"-source", sourceCompatibility,
"-target", targetCompatibility
]
}
def pomName() {
return 'Java8-specific Hibernate O/RM functionality'
}
def pomDescription() {
return 'Mainly support for Java8 Date/Time (JSR 310)'
}
def osgiDescription() {
return pomDescription()
}

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.service.ServiceRegistry;
/**
* TypeContributor for adding Java8 Date/Time specific Type implementations
*
* @author Steve Ebersole
*/
public class Java8DateTimeTypeContributor implements TypeContributor {
@Override
public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
typeContributions.contributeType( LocalDateTimeType.INSTANCE );
typeContributions.contributeType( LocalDateType.INSTANCE );
typeContributions.contributeType( LocalTimeType.INSTANCE );
}
}

View File

@ -0,0 +1,141 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
/**
* Java type descriptor for the LocalDateTime type.
*
* @author Steve Ebersole
*/
public class LocalDateJavaDescriptor extends AbstractTypeDescriptor<LocalDate> {
/**
* Singleton access
*/
public static final LocalDateJavaDescriptor INSTANCE = new LocalDateJavaDescriptor();
@SuppressWarnings("unchecked")
public LocalDateJavaDescriptor() {
super( LocalDate.class, ImmutableMutabilityPlan.INSTANCE );
}
@Override
public String toString(LocalDate value) {
return LocalDateType.FORMATTER.format( value );
}
@Override
public LocalDate fromString(String string) {
return (LocalDate) LocalDateType.FORMATTER.parse( string );
}
@Override
@SuppressWarnings("unchecked")
public <X> X unwrap(LocalDate value, Class<X> type, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( LocalDate.class.isAssignableFrom( type ) ) {
return (X) value;
}
final ZonedDateTime zonedDateTime = value.atStartOfDay().atZone( ZoneId.systemDefault() );
if ( Calendar.class.isAssignableFrom( type ) ) {
return (X) GregorianCalendar.from( zonedDateTime );
}
final Instant instant = zonedDateTime.toInstant();
if ( Timestamp.class.isAssignableFrom( type ) ) {
return (X) Timestamp.from( instant );
}
if ( java.sql.Date.class.isAssignableFrom( type ) ) {
return (X) java.sql.Date.from( instant );
}
if ( java.sql.Time.class.isAssignableFrom( type ) ) {
return (X) java.sql.Time.from( instant );
}
if ( Date.class.isAssignableFrom( type ) ) {
return (X) Date.from( instant );
}
if ( Long.class.isAssignableFrom( type ) ) {
return (X) Long.valueOf( instant.toEpochMilli() );
}
throw unknownUnwrap( type );
}
@Override
public <X> LocalDate wrap(X value, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( LocalDate.class.isInstance( value ) ) {
return (LocalDate) value;
}
if ( Timestamp.class.isInstance( value ) ) {
final Timestamp ts = (Timestamp) value;
return LocalDateTime.ofInstant( ts.toInstant(), ZoneId.systemDefault() ).toLocalDate();
}
if ( Long.class.isInstance( value ) ) {
final Instant instant = Instant.ofEpochMilli( (Long) value );
return LocalDateTime.ofInstant( instant, ZoneId.systemDefault() ).toLocalDate();
}
if ( Calendar.class.isInstance( value ) ) {
final Calendar calendar = (Calendar) value;
return LocalDateTime.ofInstant( calendar.toInstant(), calendar.getTimeZone().toZoneId() ).toLocalDate();
}
if ( Date.class.isInstance( value ) ) {
final Timestamp ts = (Timestamp) value;
final Instant instant = Instant.ofEpochMilli( ts.getTime() );
return LocalDateTime.ofInstant( instant, ZoneId.systemDefault() ).toLocalDate();
}
throw unknownWrap( value.getClass() );
}
}

View File

@ -0,0 +1,140 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
/**
* Java type descriptor for the LocalDateTime type.
*
* @author Steve Ebersole
*/
public class LocalDateTimeJavaDescriptor extends AbstractTypeDescriptor<LocalDateTime> {
/**
* Singleton access
*/
public static final LocalDateTimeJavaDescriptor INSTANCE = new LocalDateTimeJavaDescriptor();
@SuppressWarnings("unchecked")
public LocalDateTimeJavaDescriptor() {
super( LocalDateTime.class, ImmutableMutabilityPlan.INSTANCE );
}
@Override
public String toString(LocalDateTime value) {
return LocalDateTimeType.FORMATTER.format( value );
}
@Override
public LocalDateTime fromString(String string) {
return (LocalDateTime) LocalDateTimeType.FORMATTER.parse( string );
}
@Override
@SuppressWarnings("unchecked")
public <X> X unwrap(LocalDateTime value, Class<X> type, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( LocalDateTime.class.isAssignableFrom( type ) ) {
return (X) value;
}
if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) {
Instant instant = value.atZone( ZoneId.systemDefault() ).toInstant();
return (X) java.sql.Timestamp.from( instant );
}
if ( java.sql.Date.class.isAssignableFrom( type ) ) {
Instant instant = value.atZone( ZoneId.systemDefault() ).toInstant();
return (X) java.sql.Date.from( instant );
}
if ( java.sql.Time.class.isAssignableFrom( type ) ) {
Instant instant = value.atZone( ZoneId.systemDefault() ).toInstant();
return (X) java.sql.Time.from( instant );
}
if ( java.util.Date.class.isAssignableFrom( type ) ) {
Instant instant = value.atZone( ZoneId.systemDefault() ).toInstant();
return (X) java.util.Date.from( instant );
}
if ( Calendar.class.isAssignableFrom( type ) ) {
return (X) GregorianCalendar.from( value.atZone( ZoneId.systemDefault() ) );
}
if ( Long.class.isAssignableFrom( type ) ) {
Instant instant = value.atZone( ZoneId.systemDefault() ).toInstant();
return (X) Long.valueOf( instant.toEpochMilli() );
}
throw unknownUnwrap( type );
}
@Override
public <X> LocalDateTime wrap(X value, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( LocalDateTime.class.isInstance( value ) ) {
return (LocalDateTime) value;
}
if ( Timestamp.class.isInstance( value ) ) {
final Timestamp ts = (Timestamp) value;
return LocalDateTime.ofInstant( ts.toInstant(), ZoneId.systemDefault() );
}
if ( Long.class.isInstance( value ) ) {
final Instant instant = Instant.ofEpochMilli( (Long) value );
return LocalDateTime.ofInstant( instant, ZoneId.systemDefault() );
}
if ( Calendar.class.isInstance( value ) ) {
final Calendar calendar = (Calendar) value;
return LocalDateTime.ofInstant( calendar.toInstant(), calendar.getTimeZone().toZoneId() );
}
if ( Date.class.isInstance( value ) ) {
final Timestamp ts = (Timestamp) value;
final Instant instant = Instant.ofEpochMilli( ts.getTime() );
return LocalDateTime.ofInstant( instant, ZoneId.systemDefault() );
}
throw unknownWrap( value.getClass() );
}
}

View File

@ -0,0 +1,85 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Locale;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.compare.ComparableComparator;
import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;
/**
* A type that maps between {@link java.sql.Types#TIMESTAMP TIMESTAMP} and {@link LocalDateTime}.
*
* @author Steve Ebersole
*/
public class LocalDateTimeType
extends AbstractSingleColumnStandardBasicType<LocalDateTime>
implements VersionType<LocalDateTime>, LiteralType<LocalDateTime> {
/**
* Singleton access
*/
public static final LocalDateTimeType INSTANCE = new LocalDateTimeType();
static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "yyyy-mm-dd HH:mm:ss.S", Locale.ENGLISH );
public LocalDateTimeType() {
super( TimestampTypeDescriptor.INSTANCE, LocalDateTimeJavaDescriptor.INSTANCE );
}
@Override
public String getName() {
return "LocalDateTime";
}
@Override
protected boolean registerUnderJavaType() {
return true;
}
@Override
public String objectToSQLString(LocalDateTime value, Dialect dialect) throws Exception {
return "{ts '" + FORMATTER.format( value ) + "'}";
}
@Override
public LocalDateTime seed(SessionImplementor session) {
return LocalDateTime.now();
}
@Override
public LocalDateTime next(LocalDateTime current, SessionImplementor session) {
return LocalDateTime.now();
}
@Override
@SuppressWarnings("unchecked")
public Comparator<LocalDateTime> getComparator() {
return ComparableComparator.INSTANCE;
}
}

View File

@ -0,0 +1,84 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Locale;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.compare.ComparableComparator;
import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class LocalDateType
extends AbstractSingleColumnStandardBasicType<LocalDate>
implements VersionType<LocalDate>, LiteralType<LocalDate> {
/**
* Singleton access
*/
public static final LocalDateType INSTANCE = new LocalDateType();
static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "yyyy-mm-dd", Locale.ENGLISH );
public LocalDateType() {
super( TimestampTypeDescriptor.INSTANCE, LocalDateJavaDescriptor.INSTANCE );
}
@Override
public String getName() {
return "LocalDate";
}
@Override
protected boolean registerUnderJavaType() {
return true;
}
@Override
public String objectToSQLString(LocalDate value, Dialect dialect) throws Exception {
return "{d '" + FORMATTER.format( value ) + "'}";
}
@Override
public LocalDate seed(SessionImplementor session) {
return LocalDate.now();
}
@Override
public LocalDate next(LocalDate current, SessionImplementor session) {
return LocalDate.now();
}
@Override
@SuppressWarnings("unchecked")
public Comparator<LocalDate> getComparator() {
return ComparableComparator.INSTANCE;
}
}

View File

@ -0,0 +1,146 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
/**
* Java type descriptor for the LocalDateTime type.
*
* @author Steve Ebersole
*/
public class LocalTimeJavaDescriptor extends AbstractTypeDescriptor<LocalTime> {
/**
* Singleton access
*/
public static final LocalTimeJavaDescriptor INSTANCE = new LocalTimeJavaDescriptor();
@SuppressWarnings("unchecked")
public LocalTimeJavaDescriptor() {
super( LocalTime.class, ImmutableMutabilityPlan.INSTANCE );
}
@Override
public String toString(LocalTime value) {
return LocalTimeType.FORMATTER.format( value );
}
@Override
public LocalTime fromString(String string) {
return (LocalTime) LocalTimeType.FORMATTER.parse( string );
}
@Override
@SuppressWarnings("unchecked")
public <X> X unwrap(LocalTime value, Class<X> type, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( LocalDate.class.isAssignableFrom( type ) ) {
return (X) value;
}
// Oracle documentation says to set the Date to January 1, 1970 when convert from
// a LocalTime to a Calendar. IMO the same should hold true for converting to all
// the legacy Date/Time types...
final ZonedDateTime zonedDateTime = value.atDate( LocalDate.of( 1970, 1, 1 ) ).atZone( ZoneId.systemDefault() );
if ( Calendar.class.isAssignableFrom( type ) ) {
return (X) GregorianCalendar.from( zonedDateTime );
}
final Instant instant = zonedDateTime.toInstant();
if ( Timestamp.class.isAssignableFrom( type ) ) {
return (X) Timestamp.from( instant );
}
if ( java.sql.Date.class.isAssignableFrom( type ) ) {
return (X) java.sql.Date.from( instant );
}
if ( java.sql.Time.class.isAssignableFrom( type ) ) {
return (X) java.sql.Time.from( instant );
}
if ( Date.class.isAssignableFrom( type ) ) {
return (X) Date.from( instant );
}
if ( Long.class.isAssignableFrom( type ) ) {
return (X) Long.valueOf( instant.toEpochMilli() );
}
throw unknownUnwrap( type );
}
@Override
public <X> LocalTime wrap(X value, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( LocalTime.class.isInstance( value ) ) {
return (LocalTime) value;
}
if ( Timestamp.class.isInstance( value ) ) {
final Timestamp ts = (Timestamp) value;
return LocalDateTime.ofInstant( ts.toInstant(), ZoneId.systemDefault() ).toLocalTime();
}
if ( Long.class.isInstance( value ) ) {
final Instant instant = Instant.ofEpochMilli( (Long) value );
return LocalDateTime.ofInstant( instant, ZoneId.systemDefault() ).toLocalTime();
}
if ( Calendar.class.isInstance( value ) ) {
final Calendar calendar = (Calendar) value;
return LocalDateTime.ofInstant( calendar.toInstant(), calendar.getTimeZone().toZoneId() ).toLocalTime();
}
if ( Date.class.isInstance( value ) ) {
final Timestamp ts = (Timestamp) value;
final Instant instant = Instant.ofEpochMilli( ts.getTime() );
return LocalDateTime.ofInstant( instant, ZoneId.systemDefault() ).toLocalTime();
}
throw unknownWrap( value.getClass() );
}
}

View File

@ -0,0 +1,85 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Locale;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.compare.ComparableComparator;
import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;
/**
* A type that maps between {@link java.sql.Types#TIMESTAMP TIMESTAMP} and {@link java.time.LocalDateTime}.
*
* @author Steve Ebersole
*/
public class LocalTimeType
extends AbstractSingleColumnStandardBasicType<LocalTime>
implements VersionType<LocalTime>, LiteralType<LocalTime> {
/**
* Singleton access
*/
public static final LocalTimeType INSTANCE = new LocalTimeType();
static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "HH:mm:ss", Locale.ENGLISH );
public LocalTimeType() {
super( TimestampTypeDescriptor.INSTANCE, LocalTimeJavaDescriptor.INSTANCE );
}
@Override
public String getName() {
return "LocalTime";
}
@Override
protected boolean registerUnderJavaType() {
return true;
}
@Override
public String objectToSQLString(LocalTime value, Dialect dialect) throws Exception {
return "{t '" + FORMATTER.format( value ) + "'}";
}
@Override
public LocalTime seed(SessionImplementor session) {
return LocalTime.now();
}
@Override
public LocalTime next(LocalTime current, SessionImplementor session) {
return LocalTime.now();
}
@Override
@SuppressWarnings("unchecked")
public Comparator<LocalTime> getComparator() {
return ComparableComparator.INSTANCE;
}
}

View File

@ -0,0 +1 @@
org.hibernate.type.Java8DateTimeTypeContributor

View File

@ -0,0 +1,131 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.type;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Iterator;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.type.SerializableType;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
/**
* @author Steve Ebersole
*/
public class Java8DateTimeTests extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { TheEntity.class };
}
@Test
public void basicTests() {
final PersistentClass entityBinding = metadata().getEntityBinding( TheEntity.class.getName() );
final Iterator propertyBindingIterator = entityBinding.getPropertyClosureIterator();
while ( propertyBindingIterator.hasNext() ) {
final Property propertyBinding = (Property) propertyBindingIterator.next();
assertFalse(
"Found property bound as Serializable : " + propertyBinding.getName(),
propertyBinding.getType() instanceof SerializableType
);
}
TheEntity theEntity = new TheEntity( 1 );
Session s = openSession();
s.beginTransaction();
s.save( theEntity );
s.getTransaction().commit();
s.close();
s = openSession();
s.beginTransaction();
theEntity = (TheEntity) s.get( TheEntity.class, 1 );
assertNotNull( theEntity );
s.delete( theEntity );
s.getTransaction().commit();
s.close();
}
@Entity(name = "TheEntity")
@Table(name="the_entity")
public static class TheEntity {
private Integer id;
private LocalDateTime localDateTime = LocalDateTime.now();
private LocalDate localDate = LocalDate.now();
private LocalTime localTime = LocalTime.now();
public TheEntity() {
}
public TheEntity(Integer id) {
this.id = id;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public LocalDateTime getLocalDateTime() {
return localDateTime;
}
public void setLocalDateTime(LocalDateTime localDateTime) {
this.localDateTime = localDateTime;
}
public LocalDate getLocalDate() {
return localDate;
}
public void setLocalDate(LocalDate localDate) {
this.localDate = localDate;
}
public LocalTime getLocalTime() {
return localTime;
}
public void setLocalTime(LocalTime localTime) {
this.localTime = localTime;
}
}
}

View File

@ -0,0 +1,44 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# Copyright (c) 2010, Red Hat Inc. or third-party contributors as
# indicated by the @author tags or express copyright attribution
# statements applied by the authors. All third-party contributions are
# distributed under license by Red Hat Inc.
#
# This copyrighted material is made available to anyone wishing to use, modify,
# copy, or redistribute it subject to the terms and conditions of the GNU
# Lesser General Public License, as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this distribution; if not, write to:
# Free Software Foundation, Inc.
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301 USA
hibernate.dialect org.hibernate.dialect.H2Dialect
hibernate.connection.driver_class org.h2.Driver
hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE
hibernate.connection.username sa
hibernate.connection.pool_size 5
hibernate.show_sql false
hibernate.format_sql true
hibernate.max_fetch_depth 5
hibernate.cache.region_prefix hibernate.test
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory
# NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle
hibernate.jdbc.batch_versioned_data true
javax.persistence.validation.mode=NONE
hibernate.service.allow_crawling=false
hibernate.session.events.log=true

View File

@ -0,0 +1,74 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# Copyright (c) 2013, Red Hat Inc. or third-party contributors as
# indicated by the @author tags or express copyright attribution
# statements applied by the authors. All third-party contributions are
# distributed under license by Red Hat Inc.
#
# This copyrighted material is made available to anyone wishing to use, modify,
# copy, or redistribute it subject to the terms and conditions of the GNU
# Lesser General Public License, as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this distribution; if not, write to:
# Free Software Foundation, Inc.
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301 USA
#
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
#log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L (hibernateLoadPlanWalkPath->%X{hibernateLoadPlanWalkPath}) - %m%n
#log4j.appender.stdout-mdc=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout-mdc.Target=System.out
#log4j.appender.stdout-mdc.layout=org.apache.log4j.PatternLayout
#log4j.appender.stdout-mdc.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L (walk path -> %X{hibernateLoadPlanWalkPath}) - %m%n
log4j.appender.unclosedSessionFactoryFile=org.apache.log4j.FileAppender
log4j.appender.unclosedSessionFactoryFile.append=true
log4j.appender.unclosedSessionFactoryFile.file=target/tmp/log/UnclosedSessionFactoryWarnings.log
log4j.appender.unclosedSessionFactoryFile.layout=org.apache.log4j.PatternLayout
log4j.appender.unclosedSessionFactoryFile.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=info, stdout
#log4j.logger.org.hibernate.loader.plan=trace, stdout-mdc
#log4j.additivity.org.hibernate.loader.plan=false
#log4j.logger.org.hibernate.persister.walking=trace, stdout-mdc
#log4j.additivity.org.hibernate.persister.walking=false
log4j.logger.org.hibernate.tool.hbm2ddl=trace
log4j.logger.org.hibernate.testing.cache=debug
# SQL Logging - HHH-6833
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=trace
log4j.logger.org.hibernate.type.descriptor.sql.BasicExtractor=trace
log4j.logger.org.hibernate.hql.internal.ast=debug
log4j.logger.org.hibernate.sql.ordering.antlr=debug
log4j.logger.org.hibernate.loader.plan2.build.internal.LoadPlanImpl=debug
log4j.logger.org.hibernate.loader.plan2.build.spi.LoadPlanTreePrinter=debug
log4j.logger.org.hibernate.loader.plan2.exec.spi.EntityLoadQueryDetails=debug
log4j.logger.org.hibernate.engine.internal.StatisticalLoggingSessionEventListener=info
log4j.logger.org.hibernate.boot.model.source.internal.hbm.ModelBinder=debug
### When entity copy merge functionality is enabled using:
### hibernate.event.merge.entity_copy_observer=log, the following will
### provide information about merged entity copies.
### log4j.logger.org.hibernate.event.internal.EntityCopyAllowedLoggedObserver=debug
log4j.logger.org.hibernate.testing.junit4.TestClassMetadata=info, unclosedSessionFactoryFile

View File

@ -105,7 +105,7 @@ task copyBnd(type: Copy) {
into "$buildDir/osgi-lib/bnd"
}
task runBnd(type: JavaExec){
task runBnd(type: JavaExec) {
main = "-jar"
args "$buildDir/osgi-lib/bnd/bnd-2.1.0.jar", "$buildDir/osgi-lib/bnd/cdi-api.bnd", "$buildDir/osgi-lib/bnd/el-api.bnd", "$buildDir/osgi-lib/bnd/jandex.bnd"
}
@ -174,7 +174,10 @@ task testClientBundleJar(type: Jar) {
runBnd.dependsOn copyToLib
runBnd.dependsOn copyBnd
copyBnd.dependsOn copyToLib
felixProperties.dependsOn runBnd
test.dependsOn felixProperties
test.dependsOn testClientBundleJar
test.dependsOn jar

View File

@ -76,8 +76,9 @@ ext {
// Animal Sniffer Ant Task and Java 1.6 API signature file
// not using 1.9 for the time being due to MANIMALSNIFFER-34
animal_sniffer: 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.8',
java16_signature: 'org.codehaus.mojo.signature:java16:1.0@signature',
animal_sniffer: 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.13',
as_asm: 'org.ow2.asm:asm-all:5.0.3',
java16_signature: 'org.codehaus.mojo.signature:java16:1.0@signature',
//Maven plugin framework
maven_plugin: 'org.apache.maven:maven-plugin-api:3.0.5',

View File

@ -4,6 +4,14 @@ apply plugin: 'distribution'
buildDir = "target"
//project.tasks*.each {
// it.doFirst {
if ( !JavaVersion.current().java8Compatible ) {
throw new GradleException( "Release must use Java 8 or greater" )
}
// }
//}
idea.module {
}

View File

@ -3,6 +3,10 @@ include 'hibernate-testing'
include 'hibernate-entitymanager'
include 'hibernate-envers'
if ( JavaVersion.current().java8Compatible ) {
include 'hibernate-java8'
}
include 'hibernate-osgi'
include 'hibernate-c3p0'