HHH-8401 : Support fractional seconds on MySQL 5.7
(cherry picked from commit fe94cda1d1
)
This commit is contained in:
parent
c068b6f70c
commit
fa8383a22e
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2014, 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.dialect;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.dialect.function.StaticPrecisionFspTimestampFunction;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class MySQL57InnoDBDialect extends MySQL5InnoDBDialect {
|
||||
public MySQL57InnoDBDialect() {
|
||||
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 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):
|
||||
}
|
||||
}
|
|
@ -85,4 +85,8 @@ public class NoArgSQLFunction implements SQLFunction {
|
|||
}
|
||||
return hasParenthesesIfNoArguments ? name + "()" : name;
|
||||
}
|
||||
|
||||
protected String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2014, 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.dialect.function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* A function that returns a {@link org.hibernate.type.StandardBasicTypes#TIMESTAMP}
|
||||
* with static fractional seconds precision (fsp).
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class StaticPrecisionFspTimestampFunction extends NoArgSQLFunction {
|
||||
private final String renderedString;
|
||||
|
||||
/**
|
||||
* Constructs a {@link org.hibernate.type.StandardBasicTypes#TIMESTAMP} function using the
|
||||
* default fractional second precision as defined by the database.
|
||||
*
|
||||
* @param name The function name
|
||||
* @param hasParenthesesIfNoArguments Does the function call need parenthesis if there are no arguments?
|
||||
*/
|
||||
public StaticPrecisionFspTimestampFunction(String name, boolean hasParenthesesIfNoArguments) {
|
||||
super( name, StandardBasicTypes.TIMESTAMP, hasParenthesesIfNoArguments );
|
||||
renderedString = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link org.hibernate.type.StandardBasicTypes#TIMESTAMP} function using
|
||||
* the specified fractional seconds precision.
|
||||
* @param name The function name
|
||||
* @param fsp The explicit fractional seconds precision to render
|
||||
*
|
||||
* @throws java.lang.IllegalArgumentException if {@code fsp} < 0.
|
||||
*/
|
||||
public StaticPrecisionFspTimestampFunction(String name, int fsp) {
|
||||
super( name, StandardBasicTypes.TIMESTAMP);
|
||||
if ( fsp < 0 ) {
|
||||
throw new IllegalArgumentException( "fsp must be >= 0" );
|
||||
}
|
||||
renderedString = name + '(' + fsp + ')';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(Type argumentType, List args, SessionFactoryImplementor factory) throws QueryException {
|
||||
if ( args.size() > 0 ) {
|
||||
throw new QueryException( "function takes no arguments: " + getName() );
|
||||
}
|
||||
return renderedString == null ?
|
||||
super.render( argumentType, args, factory ) :
|
||||
renderedString;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2014, 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.temporal;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.dialect.MySQL57InnoDBDialect;
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner.
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-8401")
|
||||
@RequiresDialect( MySQL57InnoDBDialect.class )
|
||||
public class MySQL57TimestampFspFunctionTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testTimeStampFunctions() {
|
||||
// add an entity just so it can be queried.
|
||||
|
||||
Session s=openSession();
|
||||
Transaction tx = s.beginTransaction();
|
||||
s.persist( new Entity() );
|
||||
tx.commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
tx = s.beginTransaction();
|
||||
|
||||
// current_timestamp(), localtime(), and localtimestamp() are synonyms for now(),
|
||||
// which returns the time at which the statement began to execute.
|
||||
// the returned values for now(), current_timestamp(), localtime(), and
|
||||
// localtimestamp() should be the same.
|
||||
// sysdate() is the time at which the function itself is executed, so the
|
||||
// value returned for sysdate() should be different.
|
||||
Query q=s.createQuery(
|
||||
"select now(), current_timestamp(), localtime(), localtimestamp(), sysdate() from MySQL57TimestampFspFunctionTest$Entity"
|
||||
);
|
||||
Object[] oArray = (Object[]) q.uniqueResult();
|
||||
final Timestamp now = (Timestamp) oArray[0];
|
||||
assertEquals( now, oArray[1] );
|
||||
assertEquals( now, oArray[2] );
|
||||
assertEquals( now, oArray[3] );
|
||||
final Timestamp sysdate = (Timestamp) oArray[4];
|
||||
assertTrue( now.compareTo( sysdate ) < 0 );
|
||||
// all should have nanos > 0
|
||||
assertTrue( now.getNanos() > 0 );
|
||||
assertTrue( sysdate.getNanos() > 0 );
|
||||
|
||||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Entity.class };
|
||||
}
|
||||
|
||||
// If MySQL supported something like Oracle's "dual", then this entity wouldn't be needed.
|
||||
@javax.persistence.Entity
|
||||
@Table(name = "DummyEntity")
|
||||
public static class Entity {
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private long id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2014, Red Hat, Inc. and/or its affiliates 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.temporal;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.dialect.MySQL57InnoDBDialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.SybaseDialect;
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.SkipForDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@RequiresDialect(value = MySQL57InnoDBDialect.class)
|
||||
@TestForIssue( jiraKey = "HHH-8401")
|
||||
public class MySQL57TimestampPropertyTest extends BaseCoreFunctionalTestCase {
|
||||
private final DateFormat timestampFormat = new SimpleDateFormat("HH:mm:ss.SSS");
|
||||
|
||||
@Test
|
||||
public void testTime() {
|
||||
final Entity eOrig = new Entity();
|
||||
eOrig.ts = new Date();
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( eOrig );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Entity eGotten = (Entity) s.get( Entity.class, eOrig.id );
|
||||
final String tsOrigFormatted = timestampFormat.format( eOrig.ts );
|
||||
final String tsGottenFormatted = timestampFormat.format( eGotten.ts );
|
||||
assertEquals( tsOrigFormatted , tsGottenFormatted );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithParameter = s.createQuery( "from MySQL57TimestampPropertyTest$Entity where ts=?" ).setParameter( 0, eOrig.ts );
|
||||
final Entity eQueriedWithParameter = (Entity) queryWithParameter.uniqueResult();
|
||||
assertNotNull( eQueriedWithParameter );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithTimestamp = s.createQuery( "from MySQL57TimestampPropertyTest$Entity where ts=?" ).setTimestamp( 0, eOrig.ts );
|
||||
final Entity eQueriedWithTimestamp = (Entity) queryWithTimestamp.uniqueResult();
|
||||
assertNotNull( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.delete( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeGeneratedByColumnDefault() {
|
||||
final Entity eOrig = new Entity();
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( eOrig );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
assertNotNull( eOrig.tsColumnDefault );
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Entity eGotten = (Entity) s.get( Entity.class, eOrig.id );
|
||||
final String tsColumnDefaultOrigFormatted = timestampFormat.format( eOrig.tsColumnDefault );
|
||||
final String tsColumnDefaultGottenFormatted = timestampFormat.format( eGotten.tsColumnDefault );
|
||||
assertEquals( tsColumnDefaultOrigFormatted , tsColumnDefaultGottenFormatted );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithParameter =
|
||||
s.createQuery( "from MySQL57TimestampPropertyTest$Entity where tsColumnDefault=?" )
|
||||
.setParameter( 0, eOrig.tsColumnDefault );
|
||||
final Entity eQueriedWithParameter = (Entity) queryWithParameter.uniqueResult();
|
||||
assertNotNull( eQueriedWithParameter );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithTimestamp =
|
||||
s.createQuery( "from MySQL57TimestampPropertyTest$Entity where tsColumnDefault=?" )
|
||||
.setTimestamp( 0, eOrig.tsColumnDefault );
|
||||
final Entity eQueriedWithTimestamp = (Entity) queryWithTimestamp.uniqueResult();
|
||||
assertNotNull( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.delete( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeGeneratedByColumnDefinition() {
|
||||
final Entity eOrig = new Entity();
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( eOrig );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
assertNotNull( eOrig.tsColumnDefinition );
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Entity eGotten = (Entity) s.get( Entity.class, eOrig.id );
|
||||
final String tsColumnDefinitionOrigFormatted = timestampFormat.format( eOrig.tsColumnDefinition );
|
||||
final String tsColumnDefinitionGottenFormatted = timestampFormat.format( eGotten.tsColumnDefinition );
|
||||
assertEquals( tsColumnDefinitionOrigFormatted , tsColumnDefinitionGottenFormatted );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithParameter =
|
||||
s.createQuery( "from MySQL57TimestampPropertyTest$Entity where tsColumnDefinition=?" )
|
||||
.setParameter( 0, eOrig.tsColumnDefinition );
|
||||
final Entity eQueriedWithParameter = (Entity) queryWithParameter.uniqueResult();
|
||||
assertNotNull( eQueriedWithParameter );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithTimestamp =
|
||||
s.createQuery( "from MySQL57TimestampPropertyTest$Entity where tsColumnDefinition=?" )
|
||||
.setTimestamp( 0, eOrig.tsColumnDefinition );
|
||||
final Entity eQueriedWithTimestamp = (Entity) queryWithTimestamp.uniqueResult();
|
||||
assertNotNull( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.delete( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Entity.class };
|
||||
}
|
||||
|
||||
@javax.persistence.Entity
|
||||
public static class Entity {
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@Temporal( value = TemporalType.TIMESTAMP)
|
||||
private Date ts;
|
||||
|
||||
@Temporal( value = TemporalType.TIMESTAMP )
|
||||
@Generated( value = GenerationTime.INSERT )
|
||||
@ColumnDefault( value = "CURRENT_TIMESTAMP(6)" )
|
||||
private Date tsColumnDefault;
|
||||
|
||||
@Temporal( value = TemporalType.TIMESTAMP )
|
||||
@Generated( value = GenerationTime.INSERT )
|
||||
@Column( columnDefinition = "datetime(6) default NOW(6)" )
|
||||
private Date tsColumnDefinition;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2014, Red Hat, Inc. and/or its affiliates 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.temporal;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class TimePropertyTest extends BaseCoreFunctionalTestCase {
|
||||
private final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
@Test
|
||||
public void testTimeAsDate() {
|
||||
final Entity eOrig = new Entity();
|
||||
eOrig.tAsDate = new Time( new Date().getTime() );
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( eOrig );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Entity eGotten = (Entity) s.get( Entity.class, eOrig.id );
|
||||
// Some databases retain the milliseconds when being inserted and some don't;
|
||||
final String tAsDateOrigFormatted = timeFormat.format( eOrig.tAsDate );
|
||||
final String tAsDateGottenFormatted = timeFormat.format( eGotten.tAsDate );
|
||||
assertEquals( tAsDateOrigFormatted, tAsDateGottenFormatted );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query query = s.createQuery( "from TimePropertyTest$Entity where tAsDate=?" ).setTime( 0, eOrig.tAsDate );
|
||||
final Entity eQueried = (Entity) query.uniqueResult();
|
||||
assertNotNull( eQueried );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.delete( eQueried );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Entity.class };
|
||||
}
|
||||
|
||||
@javax.persistence.Entity
|
||||
public static class Entity {
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@Temporal( value = TemporalType.TIME )
|
||||
private java.util.Date tAsDate;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2014, Red Hat, Inc. and/or its affiliates 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.temporal;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.SybaseDialect;
|
||||
import org.hibernate.testing.SkipForDialect;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests that persisted timestamp properties have the expected format to milliseconds
|
||||
* and tests that entities can be queried by timestamp value.
|
||||
*
|
||||
* See Mysql57TimestampFspTest for tests using MySQL 5.7. MySQL 5.7 is tested separately
|
||||
* because it requires CURRENT_TIMESTAMP(6) or NOW(6) as a default.
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@SkipForDialect( value={SybaseDialect.class, MySQLDialect.class}, comment="CURRENT_TIMESTAMP not supported as default value in Sybase or MySQL" )
|
||||
public class TimestampPropertyTest extends BaseCoreFunctionalTestCase {
|
||||
private final DateFormat timestampFormat = new SimpleDateFormat("HH:mm:ss.SSS");
|
||||
|
||||
@Test
|
||||
public void testTime() {
|
||||
final Entity eOrig = new Entity();
|
||||
eOrig.ts = new Date();
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( eOrig );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Entity eGotten = (Entity) s.get( Entity.class, eOrig.id );
|
||||
final String tsOrigFormatted = timestampFormat.format( eOrig.ts );
|
||||
final String tsGottenFormatted = timestampFormat.format( eGotten.ts );
|
||||
assertEquals( tsOrigFormatted , tsGottenFormatted );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithParameter = s.createQuery( "from TimestampPropertyTest$Entity where ts=?" ).setParameter( 0, eOrig.ts );
|
||||
final Entity eQueriedWithParameter = (Entity) queryWithParameter.uniqueResult();
|
||||
assertNotNull( eQueriedWithParameter );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithTimestamp = s.createQuery( "from TimestampPropertyTest$Entity where ts=?" ).setTimestamp( 0, eOrig.ts );
|
||||
final Entity eQueriedWithTimestamp = (Entity) queryWithTimestamp.uniqueResult();
|
||||
assertNotNull( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.delete( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeGeneratedByColumnDefault() {
|
||||
final Entity eOrig = new Entity();
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( eOrig );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
assertNotNull( eOrig.tsColumnDefault );
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Entity eGotten = (Entity) s.get( Entity.class, eOrig.id );
|
||||
final String tsColumnDefaultOrigFormatted = timestampFormat.format( eOrig.tsColumnDefault );
|
||||
final String tsColumnDefaultGottenFormatted = timestampFormat.format( eGotten.tsColumnDefault );
|
||||
assertEquals( tsColumnDefaultOrigFormatted , tsColumnDefaultGottenFormatted );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithParameter =
|
||||
s.createQuery( "from TimestampPropertyTest$Entity where tsColumnDefault=?" )
|
||||
.setParameter( 0, eOrig.tsColumnDefault );
|
||||
final Entity eQueriedWithParameter = (Entity) queryWithParameter.uniqueResult();
|
||||
assertNotNull( eQueriedWithParameter );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithTimestamp =
|
||||
s.createQuery( "from TimestampPropertyTest$Entity where tsColumnDefault=?" )
|
||||
.setTimestamp( 0, eOrig.tsColumnDefault );
|
||||
final Entity eQueriedWithTimestamp = (Entity) queryWithTimestamp.uniqueResult();
|
||||
assertNotNull( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.delete( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeGeneratedByColumnDefinition() {
|
||||
final Entity eOrig = new Entity();
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( eOrig );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
assertNotNull( eOrig.tsColumnDefinition );
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Entity eGotten = (Entity) s.get( Entity.class, eOrig.id );
|
||||
final String tsColumnDefinitionOrigFormatted = timestampFormat.format( eOrig.tsColumnDefinition );
|
||||
final String tsColumnDefinitionGottenFormatted = timestampFormat.format( eGotten.tsColumnDefinition );
|
||||
assertEquals( tsColumnDefinitionOrigFormatted , tsColumnDefinitionGottenFormatted );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithParameter =
|
||||
s.createQuery( "from TimestampPropertyTest$Entity where tsColumnDefinition=?" )
|
||||
.setParameter( 0, eOrig.tsColumnDefinition );
|
||||
final Entity eQueriedWithParameter = (Entity) queryWithParameter.uniqueResult();
|
||||
assertNotNull( eQueriedWithParameter );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
final Query queryWithTimestamp =
|
||||
s.createQuery( "from TimestampPropertyTest$Entity where tsColumnDefinition=?" )
|
||||
.setTimestamp( 0, eOrig.tsColumnDefinition );
|
||||
final Entity eQueriedWithTimestamp = (Entity) queryWithTimestamp.uniqueResult();
|
||||
assertNotNull( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.delete( eQueriedWithTimestamp );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Entity.class };
|
||||
}
|
||||
|
||||
@javax.persistence.Entity
|
||||
public static class Entity {
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@Temporal( value = TemporalType.TIMESTAMP)
|
||||
private Date ts;
|
||||
|
||||
@Temporal( value = TemporalType.TIMESTAMP )
|
||||
@Generated( value = GenerationTime.INSERT )
|
||||
@ColumnDefault( value = "CURRENT_TIMESTAMP" )
|
||||
private Date tsColumnDefault;
|
||||
|
||||
@Temporal( value = TemporalType.TIMESTAMP )
|
||||
@Generated( value = GenerationTime.INSERT )
|
||||
@Column( columnDefinition = "datetime(6) default NOW(6)" )
|
||||
private Date tsColumnDefinition;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue