HHH-16240 - Add test and fix for issue, and refactor TimestampGenerators out of CurrentTimestampGeneration
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
1ff682438d
commit
6118369a56
|
@ -19,11 +19,25 @@ import org.hibernate.generator.BeforeExecutionGenerator;
|
|||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.generator.GeneratorCreationContext;
|
||||
import org.hibernate.tuple.GenerationTiming;
|
||||
import org.hibernate.tuple.TimestampGenerators;
|
||||
import org.hibernate.tuple.ValueGenerator;
|
||||
|
||||
import java.lang.reflect.Member;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.MonthDay;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.Year;
|
||||
import java.time.YearMonth;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hibernate.generator.EventTypeSets.INSERT_AND_UPDATE;
|
||||
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
|
||||
|
@ -48,30 +62,100 @@ import static org.hibernate.generator.EventTypeSets.fromArray;
|
|||
*/
|
||||
public class CurrentTimestampGeneration implements BeforeExecutionGenerator, OnExecutionGenerator {
|
||||
private final EnumSet<EventType> eventTypes;
|
||||
private final ValueGenerator<?> generator;
|
||||
|
||||
private final CurrentTimestampGeneratorDelegate delegate;
|
||||
private static final Map<Class<?>, CurrentTimestampGeneratorDelegate> generatorDelegates = new HashMap<>();
|
||||
|
||||
static {
|
||||
generatorDelegates.put(
|
||||
Date.class,
|
||||
Date::new
|
||||
);
|
||||
generatorDelegates.put(
|
||||
Calendar.class,
|
||||
() -> {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime( new Date() );
|
||||
return calendar;
|
||||
}
|
||||
);
|
||||
generatorDelegates.put(
|
||||
java.sql.Date.class,
|
||||
() -> new java.sql.Date( System.currentTimeMillis() )
|
||||
);
|
||||
|
||||
generatorDelegates.put(
|
||||
Time.class,
|
||||
() -> new Time( System.currentTimeMillis() )
|
||||
);
|
||||
generatorDelegates.put(
|
||||
Timestamp.class,
|
||||
() -> new Timestamp( System.currentTimeMillis() )
|
||||
);
|
||||
generatorDelegates.put(
|
||||
Instant.class,
|
||||
Instant::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
LocalDate.class,
|
||||
LocalDate::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
LocalDateTime.class,
|
||||
LocalDateTime::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
LocalTime.class,
|
||||
LocalTime::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
MonthDay.class,
|
||||
MonthDay::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
OffsetDateTime.class,
|
||||
OffsetDateTime::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
OffsetTime.class,
|
||||
OffsetTime::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
Year.class,
|
||||
Year::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
YearMonth.class,
|
||||
YearMonth::now
|
||||
);
|
||||
generatorDelegates.put(
|
||||
ZonedDateTime.class,
|
||||
ZonedDateTime::now
|
||||
);
|
||||
}
|
||||
|
||||
public CurrentTimestampGeneration(CurrentTimestamp annotation, Member member, GeneratorCreationContext context) {
|
||||
generator = getGenerator( annotation.source(), member );
|
||||
delegate = getGeneratorDelegate( annotation.source(), member );
|
||||
eventTypes = annotation.timing() == GenerationTiming.ALWAYS
|
||||
? fromArray( annotation.event() )
|
||||
: annotation.timing().getEquivalent().eventTypes();
|
||||
}
|
||||
|
||||
public CurrentTimestampGeneration(CreationTimestamp annotation, Member member, GeneratorCreationContext context) {
|
||||
generator = getGenerator( annotation.source(), member );
|
||||
delegate = getGeneratorDelegate( annotation.source(), member );
|
||||
eventTypes = INSERT_ONLY;
|
||||
}
|
||||
|
||||
public CurrentTimestampGeneration(UpdateTimestamp annotation, Member member, GeneratorCreationContext context) {
|
||||
generator = getGenerator( annotation.source(), member );
|
||||
delegate = getGeneratorDelegate( annotation.source(), member );
|
||||
eventTypes = INSERT_AND_UPDATE;
|
||||
}
|
||||
|
||||
private static ValueGenerator<?> getGenerator(SourceType source, Member member) {
|
||||
private static CurrentTimestampGeneratorDelegate getGeneratorDelegate(SourceType source, Member member) {
|
||||
switch (source) {
|
||||
case VM:
|
||||
// ValueGenerator is only used for in-VM generation
|
||||
return TimestampGenerators.get( ReflectHelper.getPropertyType( member ) );
|
||||
// Generator is only used for in-VM generation
|
||||
return generatorDelegates.get( ReflectHelper.getPropertyType( member ) );
|
||||
case DB:
|
||||
return null;
|
||||
default:
|
||||
|
@ -81,7 +165,7 @@ public class CurrentTimestampGeneration implements BeforeExecutionGenerator, OnE
|
|||
|
||||
@Override
|
||||
public boolean generatedOnExecution() {
|
||||
return generator == null;
|
||||
return delegate == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,7 +175,7 @@ public class CurrentTimestampGeneration implements BeforeExecutionGenerator, OnE
|
|||
|
||||
@Override
|
||||
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) {
|
||||
return generator.generateValue( session.asSessionImplementor(), owner, currentValue );
|
||||
return delegate.generate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -108,4 +192,9 @@ public class CurrentTimestampGeneration implements BeforeExecutionGenerator, OnE
|
|||
public String[] getReferencedColumnValues(Dialect dialect) {
|
||||
return new String[] { dialect.currentTimestamp() };
|
||||
}
|
||||
|
||||
private interface CurrentTimestampGeneratorDelegate {
|
||||
// Left out the Generator params, they're not used anyway. Since this is purely internal, this can be changed if needed
|
||||
Object generate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.hibernate.orm.test.annotations;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
import org.junit.Assert;
|
||||
|
@ -15,6 +17,8 @@ import java.time.*;
|
|||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
|
||||
/**
|
||||
|
@ -170,21 +174,40 @@ public class CreationTimestampTest extends BaseEntityManagerFunctionalTestCase {
|
|||
Event event = new Event();
|
||||
entityManager.persist(event);
|
||||
entityManager.flush();
|
||||
Assert.assertNotNull(event.getDate());
|
||||
Assert.assertNotNull(event.getCalendar());
|
||||
Assert.assertNotNull(event.getSqlDate());
|
||||
Assert.assertNotNull(event.getTime());
|
||||
Assert.assertNotNull(event.getTimestamp());
|
||||
Assert.assertNotNull(event.getInstant());
|
||||
Assert.assertNotNull(event.getLocalDate());
|
||||
Assert.assertNotNull(event.getLocalDateTime());
|
||||
Assert.assertNotNull(event.getLocalTime());
|
||||
Assert.assertNotNull(event.getMonthDay());
|
||||
Assert.assertNotNull(event.getOffsetDateTime());
|
||||
Assert.assertNotNull(event.getOffsetTime());
|
||||
Assert.assertNotNull(event.getYear());
|
||||
Assert.assertNotNull(event.getYearMonth());
|
||||
Assert.assertNotNull(event.getZonedDateTime());
|
||||
check( event );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-16240")
|
||||
public void generatesCurrentTimestampInStatelessSession() {
|
||||
doInJPA(this::entityManagerFactory, entityManager -> {
|
||||
Session session = entityManager.unwrap( Session.class);
|
||||
try (StatelessSession statelessSession = session.getSessionFactory().openStatelessSession()) {
|
||||
Event event = new Event();
|
||||
statelessSession.getTransaction().begin();
|
||||
statelessSession.insert(event);
|
||||
statelessSession.getTransaction().commit();
|
||||
check( event );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void check(Event event) {
|
||||
Assert.assertNotNull(event.getDate());
|
||||
Assert.assertNotNull(event.getCalendar());
|
||||
Assert.assertNotNull(event.getSqlDate());
|
||||
Assert.assertNotNull(event.getTime());
|
||||
Assert.assertNotNull(event.getTimestamp());
|
||||
Assert.assertNotNull(event.getInstant());
|
||||
Assert.assertNotNull(event.getLocalDate());
|
||||
Assert.assertNotNull(event.getLocalDateTime());
|
||||
Assert.assertNotNull(event.getLocalTime());
|
||||
Assert.assertNotNull(event.getMonthDay());
|
||||
Assert.assertNotNull(event.getOffsetDateTime());
|
||||
Assert.assertNotNull(event.getOffsetTime());
|
||||
Assert.assertNotNull(event.getYear());
|
||||
Assert.assertNotNull(event.getYearMonth());
|
||||
Assert.assertNotNull(event.getZonedDateTime());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.annotations;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
import org.junit.Assert;
|
||||
|
@ -21,6 +23,8 @@ import java.time.*;
|
|||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
|
||||
/**
|
||||
|
@ -176,21 +180,40 @@ public class UpdateTimestampTest extends BaseEntityManagerFunctionalTestCase {
|
|||
Event event = new Event();
|
||||
entityManager.persist(event);
|
||||
entityManager.flush();
|
||||
Assert.assertNotNull(event.getDate());
|
||||
Assert.assertNotNull(event.getCalendar());
|
||||
Assert.assertNotNull(event.getSqlDate());
|
||||
Assert.assertNotNull(event.getTime());
|
||||
Assert.assertNotNull(event.getTimestamp());
|
||||
Assert.assertNotNull(event.getInstant());
|
||||
Assert.assertNotNull(event.getLocalDate());
|
||||
Assert.assertNotNull(event.getLocalDateTime());
|
||||
Assert.assertNotNull(event.getLocalTime());
|
||||
Assert.assertNotNull(event.getMonthDay());
|
||||
Assert.assertNotNull(event.getOffsetDateTime());
|
||||
Assert.assertNotNull(event.getOffsetTime());
|
||||
Assert.assertNotNull(event.getYear());
|
||||
Assert.assertNotNull(event.getYearMonth());
|
||||
Assert.assertNotNull(event.getZonedDateTime());
|
||||
check( event );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-16240")
|
||||
public void generatesCurrentTimestampInStatelessSession() {
|
||||
doInJPA(this::entityManagerFactory, entityManager -> {
|
||||
Session session = entityManager.unwrap( Session.class);
|
||||
try (StatelessSession statelessSession = session.getSessionFactory().openStatelessSession()) {
|
||||
Event event = new Event();
|
||||
statelessSession.getTransaction().begin();
|
||||
statelessSession.insert(event);
|
||||
statelessSession.getTransaction().commit();
|
||||
check( event );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void check(Event event) {
|
||||
Assert.assertNotNull(event.getDate());
|
||||
Assert.assertNotNull(event.getCalendar());
|
||||
Assert.assertNotNull(event.getSqlDate());
|
||||
Assert.assertNotNull(event.getTime());
|
||||
Assert.assertNotNull(event.getTimestamp());
|
||||
Assert.assertNotNull(event.getInstant());
|
||||
Assert.assertNotNull(event.getLocalDate());
|
||||
Assert.assertNotNull(event.getLocalDateTime());
|
||||
Assert.assertNotNull(event.getLocalTime());
|
||||
Assert.assertNotNull(event.getMonthDay());
|
||||
Assert.assertNotNull(event.getOffsetDateTime());
|
||||
Assert.assertNotNull(event.getOffsetTime());
|
||||
Assert.assertNotNull(event.getYear());
|
||||
Assert.assertNotNull(event.getYearMonth());
|
||||
Assert.assertNotNull(event.getZonedDateTime());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue