diff --git a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/Client.java b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/Client.java new file mode 100644 index 0000000000..c0c4362902 --- /dev/null +++ b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/Client.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package ee.jakarta.tck.persistence.core.types.datetime; + +import java.lang.System.Logger; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.Year; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Properties; + +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import ee.jakarta.tck.persistence.common.PMClientBase; + +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.Persistence; +import jakarta.persistence.TypedQuery; + +public class Client extends PMClientBase { + + private static final Logger logger = (Logger) System.getLogger(Client.class.getName()); + + private static final long serialVersionUID = 22L; + + public Client() { + } + + public JavaArchive createDeployment() throws Exception { + + String pkgNameWithoutSuffix = Client.class.getPackageName(); + String pkgName = pkgNameWithoutSuffix + "."; + String[] classes = { pkgName + "DateTimeEntity", pkgName + "DummyEntity" }; + return createDeploymentJar("jpa_datetime.jar", pkgNameWithoutSuffix, (String[]) classes); + + } + + @Override + @BeforeEach + public void setup() throws Exception { + logger.log(Logger.Level.INFO, "Setup: Jakarta Persistence Java 8 date and time types test"); + try { + super.setup(); + createDeployment(); + Properties props = getPersistenceUnitProperties(); + props.put("jakarta.persistence.schema-generation.database.action", "drop-and-create"); + props.put("jakarta.persistence.schema-generation.create-database-schemas", "true"); + displayProperties(props); + logger.log(Logger.Level.INFO, " - executing persistence schema generation"); + Persistence.generateSchema(getPersistenceUnitName(), props); + clearEMAndEMF(); + } catch (Exception e) { + logger.log(Logger.Level.ERROR, "caught Exception: ", e); + throw new Exception(" ! Jakarta Persistence Java 8 date and time types test setup failed", e); + } + verifySchema(); + } + + @Override + @AfterEach + public void cleanup() throws Exception { + try { + logger.log(Logger.Level.INFO, "Cleanup: Jakarta Persistence 2.2 Java 8 date and time types test"); + Properties props = getPersistenceUnitProperties(); + props.put("jakarta.persistence.schema-generation.database.action", "drop"); + displayProperties(props); + logger.log(Logger.Level.INFO, " - executing persistence schema cleanup"); + Persistence.generateSchema(getPersistenceUnitName(), props); + closeEMAndEMF(); + super.cleanup(); + } finally { + removeTestJarFromCP(); + } + } + + /** Default Instant constant. */ + private static final Instant INSTANT_DEF = Instant.ofEpochSecond(0); + + /** Instant constant. */ + private static final Instant INSTANT = Instant.now(); + + /** Default LocalDate constant. */ + private static final LocalDate LOCAL_DATE_DEF = LocalDate.of(1970, 1, 1); + + /** LocalDate constant. */ + private static final LocalDate LOCAL_DATE = LocalDate.now(); + + /** Default LocalTime constant. */ + private static final LocalTime LOCAL_TIME_DEF = LocalTime.of(0, 0, 0); + + /** LocalTime constant. */ + private static final LocalTime LOCAL_TIME = LocalTime.now(); + + /** Default LocalDateTime constant. */ + private static final LocalDateTime LOCAL_DATE_TIME_DEF = LocalDateTime.of(1970, 1, 1, 0, 0, 0); + + /** LocalDateTime constant. */ + private static final LocalDateTime LOCAL_DATE_TIME = initLocalDateTime(); + + /** Default OffsetTime constant. */ + private static final OffsetTime OFFSET_TIME_DEF = OffsetTime.of(LOCAL_TIME_DEF, ZoneOffset.ofHours(1)); + + /** OffsetTime constant. */ + private static final OffsetTime OFFSET_TIME = OffsetTime.of(LOCAL_TIME, ZoneOffset.ofHours(0)); + + /** Default OffsetDateTime constant. */ + private static final OffsetDateTime OFFSET_DATE_TIME_DEF = OffsetDateTime.of(LOCAL_DATE_TIME_DEF, + ZoneOffset.ofHours(1)); + + /** OffsetDateTime constant. */ + private static final OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(LOCAL_DATE_TIME, ZoneOffset.ofHours(0)); + + /** Default Year constant. */ + private static final Year YEAR_DEF = Year.of(0); + + /** Year constant. */ + private static final Year YEAR = Year.now(); + + private static final DateTimeEntity[] entities = { + new DateTimeEntity(1L, INSTANT_DEF, LOCAL_DATE, LOCAL_TIME_DEF, LOCAL_DATE_TIME_DEF, OFFSET_TIME_DEF, + OFFSET_DATE_TIME_DEF, YEAR_DEF), + new DateTimeEntity(2L, INSTANT_DEF, LOCAL_DATE_DEF, LOCAL_TIME, LOCAL_DATE_TIME_DEF, OFFSET_TIME_DEF, + OFFSET_DATE_TIME_DEF, YEAR_DEF), + new DateTimeEntity(3L, INSTANT_DEF, LOCAL_DATE_DEF, LOCAL_TIME_DEF, LOCAL_DATE_TIME, OFFSET_TIME_DEF, + OFFSET_DATE_TIME_DEF, YEAR_DEF), + new DateTimeEntity(4L, INSTANT_DEF, LOCAL_DATE_DEF, LOCAL_TIME_DEF, LOCAL_DATE_TIME_DEF, OFFSET_TIME, + OFFSET_DATE_TIME_DEF, YEAR_DEF), + new DateTimeEntity(5L, INSTANT_DEF, LOCAL_DATE_DEF, LOCAL_TIME_DEF, LOCAL_DATE_TIME_DEF, OFFSET_TIME_DEF, + OFFSET_DATE_TIME, YEAR_DEF), + new DateTimeEntity(6L, INSTANT, LOCAL_DATE_DEF, LOCAL_TIME_DEF, LOCAL_DATE_TIME_DEF, OFFSET_TIME_DEF, + OFFSET_DATE_TIME_DEF, YEAR_DEF), + new DateTimeEntity(7L, INSTANT_DEF, LOCAL_DATE_DEF, LOCAL_TIME_DEF, LOCAL_DATE_TIME_DEF, OFFSET_TIME_DEF, + OFFSET_DATE_TIME_DEF, YEAR)}; + + // Databases precision is usually not nanoseconds. Truncate to miliseconds. + private static LocalDateTime initLocalDateTime() { + final LocalDateTime value = LocalDateTime.now(); + return value.withNano((value.getNano() / 1000000) * 1000000); + } + + /* + * @testName: dateTimeTest + * + * @assertion_ids: PERSISTENCE:JAVADOC:320; PERSISTENCE:SPEC:2118.19; + * PERSISTENCE:SPEC:2118.5; + * + * @test_Strategy: Test Jakarta Persistence date and time types: java.time.Instant, + * java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java.time.OffsetTime, + * java.time.OffsetDateTime and java.time.Year + * + * @throws com.sun.ts.lib.harness.EETest.Exception when test failed + */ + @Test + public void dateTimeTest() throws Exception { + logger.log(Logger.Level.INFO, "Test: Jakarta Persistence Java 8 date and time types"); + verifySchema(); + boolean createResult = createEntities(); + boolean allFindResult = true; + boolean[] findResults = new boolean[entities.length]; + for (int i = 0; i < entities.length; i++) { + findResults[i] = findEntityById(entities[i]); + } + boolean localDateResult = queryEntities("DateTimeEntity.findByLocalDate", "date", LOCAL_DATE, entities[0]); + boolean localTimeResult = queryEntities("DateTimeEntity.findByLocalTime", "time", LOCAL_TIME, entities[1]); + boolean localDateTimeResult = queryEntities("DateTimeEntity.findByLocalDateTime", "dateTime", LOCAL_DATE_TIME, + entities[2]); + boolean offsetTimeResult = queryEntities("DateTimeEntity.findByOffsetTime", "time", OFFSET_TIME, entities[3]); + boolean offsetDateTimeResult = queryEntities("DateTimeEntity.findByOffsetDateTime", "dateTime", + OFFSET_DATE_TIME, entities[4]); + boolean instantResult = queryEntities("DateTimeEntity.findByInstant", "instant", INSTANT, entities[5]); + boolean yearResult = queryEntities("DateTimeEntity.findByYear", "year", YEAR, entities[6]); + boolean localDateRangeResult = queryEntitiesRange("DateTimeEntity.findLocalDateRange", "min", + LOCAL_DATE.minus(10, ChronoUnit.DAYS), "max", LOCAL_DATE.plus(10, ChronoUnit.DAYS), entities[0]); + boolean localTimeRangeResult = queryEntitiesRange("DateTimeEntity.findLocalTimeRange", "min", + LOCAL_TIME.minus(10, ChronoUnit.MINUTES), "max", LOCAL_TIME.plus(10, ChronoUnit.MINUTES), entities[1]); + boolean localDateTimeRangeResult = queryEntitiesRange("DateTimeEntity.findLocalDateTimeRange", "min", + LOCAL_DATE_TIME.minus(10, ChronoUnit.DAYS), "max", LOCAL_DATE_TIME.plus(10, ChronoUnit.DAYS), + entities[2]); + boolean offsetTimeRangeResult = queryEntitiesRange("DateTimeEntity.findOffsetTimeRange", "min", + OFFSET_TIME.minus(10, ChronoUnit.MINUTES), "max", OFFSET_TIME.plus(10, ChronoUnit.MINUTES), + entities[3]); + boolean offsetDateTimeRangeResult = queryEntitiesRange("DateTimeEntity.findOffsetDateTimeRange", "min", + OFFSET_DATE_TIME.minus(10, ChronoUnit.DAYS).minus(10, ChronoUnit.MINUTES), "max", + OFFSET_DATE_TIME.plus(10, ChronoUnit.DAYS).plus(10, ChronoUnit.MINUTES), entities[4]); + boolean instantRangeResult = queryEntitiesRange("DateTimeEntity.findByInstantRange", "min", + INSTANT.minus(10, ChronoUnit.DAYS).minus(10, ChronoUnit.MINUTES), "max", + INSTANT.plus(10, ChronoUnit.DAYS).plus(10, ChronoUnit.MINUTES), entities[5]); + boolean yearRangeResult = queryEntitiesRange("DateTimeEntity.findByYearRange", "min", + YEAR.minus(10, ChronoUnit.YEARS), "max", + YEAR.plus(10, ChronoUnit.YEARS), entities[6]); + logger.log(Logger.Level.INFO, + "--------------------------------------------------------------------------------"); + logger.log(Logger.Level.INFO, " - Jakarta Persistence Java 8 date and time types test results:"); + logTestResult("Entities creation", createResult); + for (int i = 0; i < entities.length; i++) { + logTestResult("Find by ID=" + entities[i].getId().toString(), findResults[i]); + allFindResult = allFindResult && findResults[i]; + } + logTestResult("Query DateTimeEntity.findByLocalDate", localDateResult); + logTestResult("Query DateTimeEntity.findByLocalTime", localTimeResult); + logTestResult("Query DateTimeEntity.findByLocalDateTime", localDateTimeResult); + logTestResult("Query DateTimeEntity.findByOffsetTime", offsetTimeResult); + logTestResult("Query DateTimeEntity.findByOffsetDateTime", offsetDateTimeResult); + logTestResult("Query DateTimeEntity.findByInstant", instantResult); + logTestResult("Query DateTimeEntity.findByYear", yearResult); + logTestResult("Query DateTimeEntity.findLocalDateRange", localDateRangeResult); + logTestResult("Query DateTimeEntity.findLocalTimeRange", localTimeRangeResult); + logTestResult("Query DateTimeEntity.findLocalDateTimeRange", localDateTimeRangeResult); + logTestResult("Query DateTimeEntity.findOffsetTimeRange", offsetTimeRangeResult); + logTestResult("Query DateTimeEntity.findOffsetDateTimeRange", offsetDateTimeRangeResult); + logTestResult("Query DateTimeEntity.findByInstantRange", instantRangeResult); + logTestResult("Query DateTimeEntity.findByYearRange", yearRangeResult); + logger.log(Logger.Level.INFO, + "--------------------------------------------------------------------------------"); + if (!(createResult && allFindResult && localDateResult && localTimeResult && localDateTimeResult + && offsetTimeResult && offsetDateTimeResult && instantResult && yearResult + && localDateRangeResult && localTimeRangeResult && localDateTimeRangeResult + && offsetTimeRangeResult && offsetDateTimeRangeResult && instantRangeResult + && yearRangeResult)) { + throw new Exception("dateTimeTest (Jakarta Persistence Java 8 date and time types test) failed"); + } + } + + /** + * Create entities with Java 8 date and time types. + * + * @return value of {@code true} when entities were created successfully or + * {@code false} otherwise + */ + private boolean createEntities() { + logger.log(Logger.Level.INFO, " - creating test entities"); + try { + getEntityTransaction().begin(); + for (DateTimeEntity e : entities) { + getEntityManager().persist(e); + } + getEntityTransaction().commit(); + return true; + } catch (Exception e) { + logger.log(Logger.Level.ERROR, "caught Exception: ", e); + return false; + } finally { + if (getEntityTransaction().isActive()) { + getEntityTransaction().rollback(); + } + } + } + + /** + * Find entity by primary key. + * + * @param expected entity to find and compare to (must contain proper ID) + * @return value of {@code true} when entity was found and matches + * {@code expected} argument or {@code false} otherwise + */ + private boolean findEntityById(DateTimeEntity expected) { + logger.log(Logger.Level.INFO, " - executing find by ID=" + expected.getId().toString()); + try { + DateTimeEntity result = getEntityManager().find(DateTimeEntity.class, expected.getId()); + if (result == null) { + logger.log(Logger.Level.ERROR, "no result returned for " + expected.toString()); + return false; + } + if (!expected.equals(result)) { + logger.log(Logger.Level.ERROR, "returned entity does not match expected"); + logger.log(Logger.Level.ERROR, " - expected: " + expected.toString()); + logger.log(Logger.Level.ERROR, " - returned: " + result.toString()); + return false; + } + return true; + } catch (Exception e) { + logger.log(Logger.Level.ERROR, "caught Exception: ", e); + return false; + } + } + + /** + * Find entity by Java 8 date and time type value. + * + * @param queryName named query identifier (named queries are defined in + * DateTimeEntity class) + * @param paramName name of query parameter to set + * @param paramValue query parameter value to set + * @param expected expected returned entity + * @return value of {@code true} when exactly one entity was found and matches + * {@code expected} argument or {@code false} otherwise + */ + private boolean queryEntities(String queryName, String paramName, Object paramValue, DateTimeEntity expected) { + logger.log(Logger.Level.INFO, + " - executing query " + queryName + ": " + paramName + "=" + paramValue.toString()); + try { + TypedQuery query = getEntityManager().createNamedQuery(queryName, DateTimeEntity.class); + query.setParameter(paramName, paramValue); + List result = query.getResultList(); + if (result == null || result.isEmpty()) { + logger.log(Logger.Level.ERROR, "no result returned for query " + queryName + " with " + paramName + "=" + + paramValue.toString()); + return false; + } + if (result.size() > 1) { + logger.log(Logger.Level.ERROR, "too many results (" + Integer.toString(result.size()) + + ") returned for query " + queryName + " with " + paramName + "=" + paramValue.toString()); + return false; + } + DateTimeEntity returned = result.get(0); + if (!expected.equals(returned)) { + logger.log(Logger.Level.ERROR, "returned entity does not match expected"); + logger.log(Logger.Level.ERROR, " - expected: " + expected.toString()); + logger.log(Logger.Level.ERROR, " - returned: " + (returned != null ? returned.toString() : "null")); + return false; + } + return true; + } catch (Exception e) { + logger.log(Logger.Level.ERROR, "caught Exception: ", e); + return false; + } + } + + /** + * Find entity by Java 8 date and time type value. + * + * @param queryName named query identifier (named queries are defined in + * DateTimeEntity class) + * @param minName name of query parameter (for minimal value) to set + * @param minValue query parameter for a minimal value to set + * @param maxName name of query parameter (for maximal value) to set + * @param maxValue query parameter for a maximal value to set + * @param expected expected returned entity + * @return value of {@code true} when exactly one entity was found and matches + * {@code expected} argument or {@code false} otherwise + */ + private boolean queryEntitiesRange(String queryName, String minName, Object minValue, String maxName, + Object maxValue, DateTimeEntity expected) { + logger.log(Logger.Level.INFO, " - executing query " + queryName + ": " + minName + "=" + minValue.toString() + + ", " + maxName + "=" + maxValue.toString()); + try { + TypedQuery query = getEntityManager().createNamedQuery(queryName, DateTimeEntity.class); + query.setParameter(minName, minValue); + query.setParameter(maxName, maxValue); + List result = query.getResultList(); + if (result == null || result.isEmpty()) { + logger.log(Logger.Level.ERROR, "no result returned for query " + queryName + " with " + minName + "=" + + minValue.toString() + ", " + maxName + "=" + maxValue.toString()); + return false; + } + if (result.size() > 1) { + logger.log(Logger.Level.ERROR, + "too many results (" + Integer.toString(result.size()) + ") returned for query " + queryName + + " with " + minName + "=" + minValue.toString() + ", " + maxName + "=" + + maxValue.toString()); + return false; + } + DateTimeEntity returned = result.get(0); + if (!expected.equals(returned)) { + logger.log(Logger.Level.ERROR, "returned entity does not match expected"); + logger.log(Logger.Level.ERROR, " - expected: " + expected.toString()); + logger.log(Logger.Level.ERROR, " - returned: " + (returned != null ? returned.toString() : "null")); + return false; + } + return true; + } catch (Exception e) { + logger.log(Logger.Level.ERROR, "caught Exception: ", e); + return false; + } + } + + /** + * Verify generated schema. Java 8 date and time support is not finished so + * using dummy entity containing only ID to verify that schema exists. + * + * @return verification result + */ + private void verifySchema() throws Exception { + logger.log(Logger.Level.INFO, " - executing persistence schema check"); + try { + getEntityTransaction().begin(); + DummyEntity e = new DummyEntity(); + getEntityManager().persist(e); + getEntityTransaction().commit(); + logger.log(Logger.Level.TRACE, " - stored " + e.toString()); + DummyEntity result = getEntityManager().find(DummyEntity.class, e.getId()); + if (result == null) { + logger.log(Logger.Level.ERROR, " ! no entity was found"); + throw new Exception("dateTimeTest: Schema verification failed"); + } + getEntityTransaction().begin(); + result = getEntityManager().merge(result); + getEntityManager().remove(result); + getEntityTransaction().commit(); + } catch (Exception e) { + logger.log(Logger.Level.ERROR, "caught Exception: ", e); + if (getEntityTransaction().isActive()) { + getEntityTransaction().rollback(); + } + throw new Exception("dateTimeTest: Schema verification failed"); + } + } + + @Override + public EntityTransaction getEntityTransaction() { + if (isStandAloneMode() && !super.getEntityTransaction().isActive()) { + EntityTransaction et = getEntityManager().getTransaction(); + setEntityTransaction(et); + } + return super.getEntityTransaction(); + } + + /** + * Log test result message. + * + * @param name test name + * @param result test result + */ + private void logTestResult(String name, boolean result) { + StringBuilder sb = new StringBuilder(); + sb.append(" ").append(result ? '+' : '-').append(' '); + sb.append(name).append(": "); + sb.append(result ? "PASSED" : "FAILED"); + logger.log(Logger.Level.INFO, sb.toString()); + } + +} diff --git a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/DateTimeEntity.java b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/DateTimeEntity.java new file mode 100644 index 0000000000..08179de81b --- /dev/null +++ b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/DateTimeEntity.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package ee.jakarta.tck.persistence.core.types.datetime; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.Year; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.NamedQuery; +import jakarta.persistence.Table; + +/** + * Entity containing new JPA date and time types. + */ +@Entity +@Table(name = "DATATYPES_DATE_TIME") +// Query on exact value match. +@NamedQuery(name = "DateTimeEntity.findByLocalDate", query = "SELECT e FROM DateTimeEntity e WHERE e.localDate = :date") +@NamedQuery(name = "DateTimeEntity.findByLocalTime", query = "SELECT e FROM DateTimeEntity e WHERE e.localTimeAttr = :time") +@NamedQuery(name = "DateTimeEntity.findByLocalDateTime", query = "SELECT e FROM DateTimeEntity e WHERE e.localDateTime = :dateTime") +@NamedQuery(name = "DateTimeEntity.findByOffsetTime", query = "SELECT e FROM DateTimeEntity e WHERE e.offsetTime = :time") +@NamedQuery(name = "DateTimeEntity.findByOffsetDateTime", query = "SELECT e FROM DateTimeEntity e WHERE e.offsetDateTime = :dateTime") +@NamedQuery(name = "DateTimeEntity.findByInstant", query = "SELECT e FROM DateTimeEntity e WHERE e.instantAttr = :instant") +@NamedQuery(name = "DateTimeEntity.findByYear", query = "SELECT e FROM DateTimeEntity e WHERE e.yearAttr = :year") +// Query on values range match. +@NamedQuery(name = "DateTimeEntity.findLocalDateRange", query = "SELECT e FROM DateTimeEntity e WHERE e.localDate > :min AND e.localDate < :max") +@NamedQuery(name = "DateTimeEntity.findLocalTimeRange", query = "SELECT e FROM DateTimeEntity e WHERE e.localTimeAttr > :min AND e.localTimeAttr < :max") +@NamedQuery(name = "DateTimeEntity.findLocalDateTimeRange", query = "SELECT e FROM DateTimeEntity e WHERE e.localDateTime > :min AND e.localDateTime < :max") +@NamedQuery(name = "DateTimeEntity.findOffsetTimeRange", query = "SELECT e FROM DateTimeEntity e WHERE e.offsetTime > :min AND e.offsetTime < :max") +@NamedQuery(name = "DateTimeEntity.findOffsetDateTimeRange", query = "SELECT e FROM DateTimeEntity e WHERE e.offsetDateTime > :min AND e.offsetDateTime < :max") +@NamedQuery(name = "DateTimeEntity.findByInstantRange", query = "SELECT e FROM DateTimeEntity e WHERE e.instantAttr > :min AND e.instantAttr < :max") +@NamedQuery(name = "DateTimeEntity.findByYearRange", query = "SELECT e FROM DateTimeEntity e WHERE e.yearAttr > :min AND e.yearAttr < :max") +public class DateTimeEntity implements java.io.Serializable { + private static final long serialVersionUID = 22L; + + /** Entity primary key. */ + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + Long id; + + /** Java 8 Instant attribute. + * From Jakarta Persistence 3.2 + **/ + private Instant instantAttr; + + /** Java 8 LocalDate attribute. */ + private LocalDate localDate; + + // LOCALTIME is MySQL keyword so using another name for this attribute. + /** Java 8 LocalTime attribute. */ + private LocalTime localTimeAttr; + + /** Java 8 LocalDateTime attribute. */ + private LocalDateTime localDateTime; + + /** Java 8 OffsetTime attribute. */ + private OffsetTime offsetTime; + + /** Java 8 OffsetDateTime attribute. */ + private OffsetDateTime offsetDateTime; + + /** Java 8 Instant attribute. + * From Jakarta Persistence 3.2 + **/ + private Year yearAttr; + + /** + * Creates an instance of Java 9 date and time entity. Entity attributes are not + * initialized. + */ + public DateTimeEntity() { + } + + /** + * Creates an instance of Java 9 date and time entity. Entity attributes are + * initialized using provided values. + * + * @param id date and time entity primary key + * @param instant Java 8 Instant attribute + * @param localDate Java 8 LocalDate attribute + * @param localTime Java 8 LocalTime attribute + * @param localDateTime Java 8 LocalDateTime attribute + * @param offsetTime Java 8 OffsetTime attribute + * @param offsetDateTime Java 8 OffsetDateTime attribute + * @param year Java 8 Year attribute + */ + public DateTimeEntity(Long id, Instant instant, LocalDate localDate, LocalTime localTime, LocalDateTime localDateTime, + OffsetTime offsetTime, OffsetDateTime offsetDateTime, Year year) { + // bug 27376147:as a result of GenerationType.Auto, + // Client is picking incorrect ID values + // this.id = id; + + this.instantAttr = instant; + this.localDate = localDate; + this.localTimeAttr = localTime; + this.localDateTime = localDateTime; + this.offsetTime = offsetTime; + this.offsetDateTime = offsetDateTime; + this.yearAttr = year; + } + + /** + * Get entity primary key. + * + * @return primary key + */ + public Long getId() { + return id; + } + + /** + * Set entity primary key. + * + * @param id primary key to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * Get Java 8 Instant attribute. + * + * @return Instant attribute + */ + java.time.Instant getInstantAttr() { + return instantAttr; + } + + /** + * Set Java 8 Instant attribute. + * + * @param instantAttr Instant attribute to set + */ + void setInstantAttr(java.time.Instant instantAttr) { + this.instantAttr = instantAttr; + } + + /** + * Get Java 8 LocalDate attribute. + * + * @return LocalDate attribute + */ + java.time.LocalDate getLocalDate() { + return localDate; + } + + /** + * Set Java 8 LocalDate attribute. + * + * @param localDate LocalDate attribute to set + */ + void setLocalDate(java.time.LocalDate localDate) { + this.localDate = localDate; + } + + /** + * Get Java 8 LocalTime attribute. + * + * @return LocalTime attribute + */ + java.time.LocalTime getLocalTime() { + return localTimeAttr; + } + + /** + * Set Java 8 LocalTime attribute. + * + * @param localTime LocalTime attribute to set + */ + void setLocalTime(java.time.LocalTime localTime) { + this.localTimeAttr = localTime; + } + + /** + * Get Java 8 LocalDateTime attribute. + * + * @return LocalDateTime attribute + */ + java.time.LocalDateTime getLocalDateTime() { + return localDateTime; + } + + /** + * Get Java 8 LocalDateTime attribute. + * + * @param localDateTime LocalDateTime attribute to set + */ + void setLocalDateTime(java.time.LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + /** + * Get Java 8 OffsetTime attribute. + * + * @return OffsetTime attribute + */ + java.time.OffsetTime getOffsetTime() { + return offsetTime; + } + + /** + * Set Java 8 OffsetTime attribute. + * + * @param offsetTime OffsetTime attribute to set + */ + void setOffsetTime(java.time.OffsetTime offsetTime) { + this.offsetTime = offsetTime; + } + + /** + * Get Java 8 OffsetDateTime attribute. + * + * @return OffsetDateTime attribute + */ + java.time.OffsetDateTime getOffsetDateTime() { + return offsetDateTime; + } + + /** + * Set Java 8 OffsetDateTime attribute. + * + * @param offsetDateTime OffsetDateTime attribute to set + */ + void setOffsetDateTime(java.time.OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } + + /** + * Get Java 8 Year attribute. + * + * @return Year attribute + */ + java.time.Year getYearAttr() { + return yearAttr; + } + + /** + * Set Java 8 Year attribute. + * + * @param yearAttr Year attribute to set + */ + void setYearAttr(java.time.Year yearAttr) { + this.yearAttr = yearAttr; + } + + @Override + public int hashCode() { + return (id != null ? id.hashCode() : 0); + } + + @Override + public boolean equals(Object object) { + if (object instanceof DateTimeEntity) { + final DateTimeEntity other = (DateTimeEntity) object; + return (this.id == null && other.id == null) || this.id != null && this.id.equals(other.id); + } else { + return false; + } + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append(this.getClass().getSimpleName()).append('['); + result.append("id=").append(id != null ? id.toString() : "null"); + result.append(','); + result.append("instant=").append(instantAttr != null ? instantAttr.toString() : "null"); + result.append(','); + result.append("localDate=").append(localDate != null ? localDate.toString() : "null"); + result.append(','); + result.append("localTime=").append(localTimeAttr != null ? localTimeAttr.toString() : "null"); + result.append(','); + result.append("localDateTime=").append(localDateTime != null ? localDateTime.toString() : "null"); + result.append(','); + result.append("offsetTime=").append(offsetTime != null ? offsetTime.toString() : "null"); + result.append(','); + result.append("offsetDateTime=").append(offsetDateTime != null ? offsetDateTime.toString() : "null"); + result.append(','); + result.append("year=").append(yearAttr != null ? yearAttr.toString() : "null"); + result.append(']'); + return result.toString(); + } + +} diff --git a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/DummyEntity.java b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/DummyEntity.java new file mode 100644 index 0000000000..35b423cbf6 --- /dev/null +++ b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/core/types/datetime/DummyEntity.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package ee.jakarta.tck.persistence.core.types.datetime; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +/** + * Dummy JPA entity used to verify schema generation process. + */ +@Entity +@Table(name = "DT_DUMMY_ENTITY") +public class DummyEntity implements java.io.Serializable { + private static final long serialVersionUID = 22L; + + /** + * Creates an instance of dummy entity. Entity attributes are not initialized. + */ + public DummyEntity() { + } + + /** + * Creates an instance of dummy entity. Entity attributes are initialized using + * provided values. + * + * @param id dummy entity primary key + */ + public DummyEntity(Long id) { + this.id = id; + } + + /** Entity primary key. */ + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + Long id; + + /** + * Get entity primary key. + * + * @return primary key + */ + public Long getId() { + return id; + } + + /** + * Set entity primary key. + * + * @param id primary key to set + */ + public void setId(Long id) { + this.id = id; + } + + @Override + public int hashCode() { + return (id != null ? id.hashCode() : 0); + } + + @Override + public boolean equals(Object object) { + if (object instanceof DummyEntity) { + final DummyEntity other = (DummyEntity) object; + return (this.id == null && other.id == null) || this.id != null && this.id.equals(other.id); + } else { + return false; + } + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append(this.getClass().getSimpleName()).append('['); + result.append("id=").append(id != null ? id.toString() : "null"); + result.append(']'); + return result.toString(); + } + +} diff --git a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/Client.java b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/Client.java deleted file mode 100755 index aa756c1039..0000000000 --- a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/Client.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package ee.jakarta.tck.persistence.jpa22.datetime; - -import java.lang.System.Logger; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.ZoneOffset; -import java.time.temporal.ChronoUnit; -import java.util.List; -import java.util.Properties; - -import org.jboss.shrinkwrap.api.spec.JavaArchive; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import ee.jakarta.tck.persistence.common.PMClientBase; - -import jakarta.persistence.EntityTransaction; -import jakarta.persistence.Persistence; -import jakarta.persistence.TypedQuery; - -public class Client extends PMClientBase { - - private static final Logger logger = (Logger) System.getLogger(Client.class.getName()); - - private static final long serialVersionUID = 22L; - - String schemaGenerationDir = null; - - public Client() { - } - - public JavaArchive createDeployment() throws Exception { - - String pkgNameWithoutSuffix = Client.class.getPackageName(); - String pkgName = pkgNameWithoutSuffix + "."; - String[] classes = { pkgName + "DateTimeEntity", pkgName + "DummyEntity" }; - return createDeploymentJar("jpa_jpa22_datetime.jar", pkgNameWithoutSuffix, (String[]) classes); - - } - - @Override - @BeforeEach - public void setup() throws Exception { - logger.log(Logger.Level.INFO, "Setup: JPA 2.2 Java 8 date and time types test"); - try { - super.setup(); - createDeployment(); - Properties props = getPersistenceUnitProperties(); - props.put("jakarta.persistence.schema-generation.database.action", "drop-and-create"); - props.put("jakarta.persistence.schema-generation.create-database-schemas", "true"); - displayProperties(props); - logger.log(Logger.Level.INFO, " - executing persistence schema generation"); - Persistence.generateSchema(getPersistenceUnitName(), props); - clearEMAndEMF(); - } catch (Exception e) { - logger.log(Logger.Level.ERROR, "caught Exception: ", e); - throw new Exception(" ! JPA 2.2 Java 8 date and time types test setup failed", e); - } - verifySchema(); - } - - @Override - @AfterEach - public void cleanup() throws Exception { - try { - logger.log(Logger.Level.INFO, "Cleanup: JPA 2.2 Java 8 date and time types test"); - Properties props = getPersistenceUnitProperties(); - props.put("jakarta.persistence.schema-generation.database.action", "drop"); - displayProperties(props); - logger.log(Logger.Level.INFO, " - executing persistence schema cleanup"); - Persistence.generateSchema(getPersistenceUnitName(), props); - closeEMAndEMF(); - super.cleanup(); - } finally { - removeTestJarFromCP(); - } - } - - /** Default LocalDate constant. */ - private static final LocalDate LOCAL_DATE_DEF = LocalDate.of(1970, 1, 1); - - /** LocalDate constant. */ - private static final LocalDate LOCAL_DATE = LocalDate.now(); - - /** Default LocalTime constant. */ - private static final LocalTime LOCAL_TIME_DEF = LocalTime.of(0, 0, 0); - - /** LocalTime constant. */ - private static final LocalTime LOCAL_TIME = LocalTime.now(); - - /** Default LocalDateTime constant. */ - private static final LocalDateTime LOCAL_DATE_TIME_DEF = LocalDateTime.of(1970, 1, 1, 0, 0, 0); - - /** LocalDateTime constant. */ - private static final LocalDateTime LOCAL_DATE_TIME = initLocalDateTime(); - - /** Default OffsetTime constant. */ - private static final OffsetTime OFFSET_TIME_DEF = OffsetTime.of(LOCAL_TIME_DEF, ZoneOffset.ofHours(1)); - - /** OffsetTime constant. */ - private static final OffsetTime OFFSET_TIME = OffsetTime.of(LOCAL_TIME, ZoneOffset.ofHours(0)); - - /** Default OffsetDateTime constant. */ - private static final OffsetDateTime OFFSET_DATE_TIME_DEF = OffsetDateTime.of(LOCAL_DATE_TIME_DEF, - ZoneOffset.ofHours(1)); - - /** OffsetDateTime constant. */ - private static final OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(LOCAL_DATE_TIME, ZoneOffset.ofHours(0)); - - private static final DateTimeEntity[] entities = { - new DateTimeEntity(1L, LOCAL_DATE, LOCAL_TIME_DEF, LOCAL_DATE_TIME_DEF, OFFSET_TIME_DEF, - OFFSET_DATE_TIME_DEF), - new DateTimeEntity(2L, LOCAL_DATE_DEF, LOCAL_TIME, LOCAL_DATE_TIME_DEF, OFFSET_TIME_DEF, - OFFSET_DATE_TIME_DEF), - new DateTimeEntity(3L, LOCAL_DATE_DEF, LOCAL_TIME_DEF, LOCAL_DATE_TIME, OFFSET_TIME_DEF, - OFFSET_DATE_TIME_DEF), - new DateTimeEntity(4L, LOCAL_DATE_DEF, LOCAL_TIME_DEF, LOCAL_DATE_TIME_DEF, OFFSET_TIME, - OFFSET_DATE_TIME_DEF), - new DateTimeEntity(5L, LOCAL_DATE_DEF, LOCAL_TIME_DEF, LOCAL_DATE_TIME_DEF, OFFSET_TIME_DEF, - OFFSET_DATE_TIME) }; - - // Databases precision is usually not nanoseconds. Truncate to miliseconds. - private static LocalDateTime initLocalDateTime() { - final LocalDateTime value = LocalDateTime.now(); - return value.withNano((value.getNano() / 1000000) * 1000000); - } - - /* - * @testName: dateTimeTest - * - * @assertion_ids: PERSISTENCE:JAVADOC:320; PERSISTENCE:SPEC:2118.19; - * PERSISTENCE:SPEC:2118.5; - * - * @test_Strategy: Test new JPA 2.2 date and time types: java.time.LocalDate, - * java.time.LocalTime, java.time.LocalDateTime, java.time.OffsetTime and - * java.time.OffsetDateTime - * - * @throws com.sun.ts.lib.harness.EETest.Exception when test failed - */ - @Test - public void dateTimeTest() throws Exception { - logger.log(Logger.Level.INFO, "Test: JPA 2.2 Java 8 date and time types"); - verifySchema(); - boolean createResult = createEntities(); - boolean allFindResult = true; - boolean[] findResults = new boolean[entities.length]; - for (int i = 0; i < entities.length; i++) { - findResults[i] = findEntityById(entities[i]); - } - boolean localDateResult = queryEntities("DateTimeEntity.findByLocalDate", "date", LOCAL_DATE, entities[0]); - boolean localTimeResult = queryEntities("DateTimeEntity.findByLocalTime", "time", LOCAL_TIME, entities[1]); - boolean localDateTimeResult = queryEntities("DateTimeEntity.findByLocalDateTime", "dateTime", LOCAL_DATE_TIME, - entities[2]); - boolean offsetTimeResult = queryEntities("DateTimeEntity.findByOffsetTime", "time", OFFSET_TIME, entities[3]); - boolean offsetDateTimeResult = queryEntities("DateTimeEntity.findByOffsetDateTime", "dateTime", - OFFSET_DATE_TIME, entities[4]); - boolean localDateRangeResult = queryEntitiesRange("DateTimeEntity.findLocalDateRange", "min", - LOCAL_DATE.minus(10, ChronoUnit.DAYS), "max", LOCAL_DATE.plus(10, ChronoUnit.DAYS), entities[0]); - boolean localTimeRangeResult = queryEntitiesRange("DateTimeEntity.findLocalTimeRange", "min", - LOCAL_TIME.minus(10, ChronoUnit.MINUTES), "max", LOCAL_TIME.plus(10, ChronoUnit.MINUTES), entities[1]); - boolean localDateTimeRangeResult = queryEntitiesRange("DateTimeEntity.findLocalDateTimeRange", "min", - LOCAL_DATE_TIME.minus(10, ChronoUnit.DAYS), "max", LOCAL_DATE_TIME.plus(10, ChronoUnit.DAYS), - entities[2]); - boolean offsetTimeRangeResult = queryEntitiesRange("DateTimeEntity.findOffsetTimeRange", "min", - OFFSET_TIME.minus(10, ChronoUnit.MINUTES), "max", OFFSET_TIME.plus(10, ChronoUnit.MINUTES), - entities[3]); - boolean offsetDateTimeRangeResult = queryEntitiesRange("DateTimeEntity.findOffsetDateTimeRange", "min", - OFFSET_DATE_TIME.minus(10, ChronoUnit.DAYS).minus(10, ChronoUnit.MINUTES), "max", - OFFSET_DATE_TIME.plus(10, ChronoUnit.DAYS).plus(10, ChronoUnit.MINUTES), entities[4]); - logger.log(Logger.Level.INFO, - "--------------------------------------------------------------------------------"); - logger.log(Logger.Level.INFO, " - JPA 2.2 Java 8 date and time types test results:"); - logTestResult("Entities creation", createResult); - for (int i = 0; i < entities.length; i++) { - logTestResult("Find by ID=" + entities[i].getId().toString(), findResults[i]); - allFindResult = allFindResult && findResults[i]; - } - logTestResult("Query DateTimeEntity.findByLocalDate", localDateResult); - logTestResult("Query DateTimeEntity.findByLocalTime", localTimeResult); - logTestResult("Query DateTimeEntity.findByLocalDateTime", localDateTimeResult); - logTestResult("Query DateTimeEntity.findByOffsetTime", offsetTimeResult); - logTestResult("Query DateTimeEntity.findByOffsetDateTime", offsetDateTimeResult); - logTestResult("Query DateTimeEntity.findLocalDateRange", localDateRangeResult); - logTestResult("Query DateTimeEntity.findLocalTimeRange", localTimeRangeResult); - logTestResult("Query DateTimeEntity.findLocalDateTimeRange", localDateTimeRangeResult); - logTestResult("Query DateTimeEntity.findOffsetTimeRange", offsetTimeRangeResult); - logTestResult("Query DateTimeEntity.findOffsetDateTimeRange", offsetDateTimeRangeResult); - logger.log(Logger.Level.INFO, - "--------------------------------------------------------------------------------"); - if (!(createResult && allFindResult && localDateResult && localTimeResult && localDateTimeResult - && offsetTimeResult && offsetDateTimeResult)) { - throw new Exception("dateTimeTest (JPA 2.2 Java 8 date and time types test) failed"); - } - } - - /** - * Create entities with Java 8 date and time types. - * - * @return value of {@code true} when entities were created successfully or - * {@code false} otherwise - */ - private boolean createEntities() { - logger.log(Logger.Level.INFO, " - creating test entities"); - try { - getEntityTransaction().begin(); - for (DateTimeEntity e : entities) { - getEntityManager().persist(e); - } - getEntityTransaction().commit(); - return true; - } catch (Exception e) { - logger.log(Logger.Level.ERROR, "caught Exception: ", e); - return false; - } finally { - if (getEntityTransaction().isActive()) { - getEntityTransaction().rollback(); - } - } - } - - /** - * Find entity by primary key. - * - * @param expected entity to find and compare to (must contain proper ID) - * @return value of {@code true} when entity was found and matches - * {@code expected} argument or {@code false} otherwise - */ - private boolean findEntityById(DateTimeEntity expected) { - logger.log(Logger.Level.INFO, " - executing find by ID=" + expected.getId().toString()); - try { - DateTimeEntity result = getEntityManager().find(DateTimeEntity.class, expected.getId()); - if (result == null) { - logger.log(Logger.Level.ERROR, "no result returned for " + expected.toString()); - return false; - } - if (!expected.equals(result)) { - logger.log(Logger.Level.ERROR, "returned entity does not match expected"); - logger.log(Logger.Level.ERROR, " - expected: " + expected.toString()); - logger.log(Logger.Level.ERROR, " - returned: " + result.toString()); - return false; - } - return true; - } catch (Exception e) { - logger.log(Logger.Level.ERROR, "caught Exception: ", e); - return false; - } - } - - /** - * Find entity by Java 8 date and time type value. - * - * @param queryName named query identifier (named queries are defined in - * DateTimeEntity class) - * @param paramName name of query parameter to set - * @param paramValue query parameter value to set - * @param expected expected returned entity - * @return value of {@code true} when exactly one entity was found and matches - * {@code expected} argument or {@code false} otherwise - */ - private boolean queryEntities(String queryName, String paramName, Object paramValue, DateTimeEntity expected) { - logger.log(Logger.Level.INFO, - " - executing query " + queryName + ": " + paramName + "=" + paramValue.toString()); - try { - TypedQuery query = getEntityManager().createNamedQuery(queryName, DateTimeEntity.class); - query.setParameter(paramName, paramValue); - List result = query.getResultList(); - if (result == null || result.isEmpty()) { - logger.log(Logger.Level.ERROR, "no result returned for query " + queryName + " with " + paramName + "=" - + paramValue.toString()); - return false; - } - if (result.size() > 1) { - logger.log(Logger.Level.ERROR, "too many results (" + Integer.toString(result.size()) - + ") returned for query " + queryName + " with " + paramName + "=" + paramValue.toString()); - return false; - } - DateTimeEntity returned = result.get(0); - if (!expected.equals(returned)) { - logger.log(Logger.Level.ERROR, "returned entity does not match expected"); - logger.log(Logger.Level.ERROR, " - expected: " + expected.toString()); - logger.log(Logger.Level.ERROR, " - returned: " + (returned != null ? returned.toString() : "null")); - return false; - } - return true; - } catch (Exception e) { - logger.log(Logger.Level.ERROR, "caught Exception: ", e); - return false; - } - } - - /** - * Find entity by Java 8 date and time type value. - * - * @param queryName named query identifier (named queries are defined in - * DateTimeEntity class) - * @param paramName name of query parameter to set - * @param paramValue query parameter value to set - * @param expected expected returned entity - * @return value of {@code true} when exactly one entity was found and matches - * {@code expected} argument or {@code false} otherwise - */ - private boolean queryEntitiesRange(String queryName, String minName, Object minValue, String maxName, - Object maxValue, DateTimeEntity expected) { - logger.log(Logger.Level.INFO, " - executing query " + queryName + ": " + minName + "=" + minValue.toString() - + ", " + maxName + "=" + maxValue.toString()); - try { - TypedQuery query = getEntityManager().createNamedQuery(queryName, DateTimeEntity.class); - query.setParameter(minName, minValue); - query.setParameter(maxName, maxValue); - List result = query.getResultList(); - if (result == null || result.isEmpty()) { - logger.log(Logger.Level.ERROR, "no result returned for query " + queryName + " with " + minName + "=" - + minValue.toString() + ", " + maxName + "=" + maxValue.toString()); - return false; - } - if (result.size() > 1) { - logger.log(Logger.Level.ERROR, - "too many results (" + Integer.toString(result.size()) + ") returned for query " + queryName - + " with " + minName + "=" + minValue.toString() + ", " + maxName + "=" - + maxValue.toString()); - return false; - } - DateTimeEntity returned = result.get(0); - if (!expected.equals(returned)) { - logger.log(Logger.Level.ERROR, "returned entity does not match expected"); - logger.log(Logger.Level.ERROR, " - expected: " + expected.toString()); - logger.log(Logger.Level.ERROR, " - returned: " + (returned != null ? returned.toString() : "null")); - return false; - } - return true; - } catch (Exception e) { - logger.log(Logger.Level.ERROR, "caught Exception: ", e); - return false; - } - } - - /** - * Verify generated schema. Java 8 date and time support is not finished so - * using dummy entity containing only ID to verify that schema exists. - * - * @return verification result - */ - private void verifySchema() throws Exception { - logger.log(Logger.Level.INFO, " - executing persistence schema check"); - try { - getEntityTransaction().begin(); - DummyEntity e = new DummyEntity(); - getEntityManager().persist(e); - getEntityTransaction().commit(); - logger.log(Logger.Level.TRACE, " - stored " + e.toString()); - DummyEntity result = getEntityManager().find(DummyEntity.class, e.getId()); - if (result == null) { - logger.log(Logger.Level.ERROR, " ! no entity was found"); - throw new Exception("dateTimeTest: Schema verification failed"); - } - getEntityTransaction().begin(); - result = getEntityManager().merge(result); - getEntityManager().remove(result); - getEntityTransaction().commit(); - } catch (Exception e) { - logger.log(Logger.Level.ERROR, "caught Exception: ", e); - if (getEntityTransaction().isActive()) { - getEntityTransaction().rollback(); - } - throw new Exception("dateTimeTest: Schema verification failed"); - } - } - - @Override - public EntityTransaction getEntityTransaction() { - if (isStandAloneMode() && !super.getEntityTransaction().isActive()) { - EntityTransaction et = getEntityManager().getTransaction(); - setEntityTransaction(et); - } - return super.getEntityTransaction(); - } - - /** - * Log test result message. - * - * @param name test name - * @param result test result - */ - private void logTestResult(String name, boolean result) { - StringBuilder sb = new StringBuilder(); - sb.append(" ").append(result ? '+' : '-').append(' '); - sb.append(name).append(": "); - sb.append(result ? "PASSED" : "FAILED"); - logger.log(Logger.Level.INFO, sb.toString()); - } - -} diff --git a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/DateTimeEntity.java b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/DateTimeEntity.java deleted file mode 100644 index 5d997d4f11..0000000000 --- a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/DateTimeEntity.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package ee.jakarta.tck.persistence.jpa22.datetime; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.NamedQuery; -import jakarta.persistence.Table; - -/** - * Entity containing new JPA 2.2 date and time types. - */ -@Entity -@Table(name = "JPA22_DT_DATE_TIME_ENTITY") -// Query on exact value match. -@NamedQuery(name = "DateTimeEntity.findByLocalDate", query = "SELECT e FROM DateTimeEntity e WHERE e.localDate = :date") -@NamedQuery(name = "DateTimeEntity.findByLocalTime", query = "SELECT e FROM DateTimeEntity e WHERE e.localTimeAttr = :time") -@NamedQuery(name = "DateTimeEntity.findByLocalDateTime", query = "SELECT e FROM DateTimeEntity e WHERE e.localDateTime = :dateTime") -@NamedQuery(name = "DateTimeEntity.findByOffsetTime", query = "SELECT e FROM DateTimeEntity e WHERE e.offsetTime = :time") -@NamedQuery(name = "DateTimeEntity.findByOffsetDateTime", query = "SELECT e FROM DateTimeEntity e WHERE e.offsetDateTime = :dateTime") -// Query on values range match. -@NamedQuery(name = "DateTimeEntity.findLocalDateRange", query = "SELECT e FROM DateTimeEntity e WHERE e.localDate > :min AND e.localDate < :max") -@NamedQuery(name = "DateTimeEntity.findLocalTimeRange", query = "SELECT e FROM DateTimeEntity e WHERE e.localTimeAttr > :min AND e.localTimeAttr < :max") -@NamedQuery(name = "DateTimeEntity.findLocalDateTimeRange", query = "SELECT e FROM DateTimeEntity e WHERE e.localDateTime > :min AND e.localDateTime < :max") -@NamedQuery(name = "DateTimeEntity.findOffsetTimeRange", query = "SELECT e FROM DateTimeEntity e WHERE e.offsetTime > :min AND e.offsetTime < :max") -@NamedQuery(name = "DateTimeEntity.findOffsetDateTimeRange", query = "SELECT e FROM DateTimeEntity e WHERE e.offsetDateTime > :min AND e.offsetDateTime < :max") -public class DateTimeEntity implements java.io.Serializable { - private static final long serialVersionUID = 22L; - - /** Entity primary key. */ - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - Long id; - - /** Java 8 LocalDate attribute. */ - private LocalDate localDate; - - // LOCALTIME is MySQL keyword so using another name for this attribute. - /** Java 8 LocalTime attribute. */ - private LocalTime localTimeAttr; - - /** Java 8 LocalDateTime attribute. */ - private LocalDateTime localDateTime; - - /** Java 8 OffsetTime attribute. */ - private OffsetTime offsetTime; - - /** Java 8 OffsetDateTime attribute. */ - private OffsetDateTime offsetDateTime; - - /** - * Creates an instance of Java 9 date and time entity. Entity attributes are not - * initialized. - */ - public DateTimeEntity() { - } - - /** - * Creates an instance of Java 9 date and time entity. Entity attributes are - * initialized using provided values. - * - * @param id date and time entity primary key - * @param localDate Java 8 LocalDate attribute - * @param localTime Java 8 LocalTime attribute - * @param localDateTime Java 8 LocalDateTime attribute - * @param offsetTime Java 8 OffsetTime attribute - * @param offsetDateTime Java 8 OffsetDateTime attribute - */ - public DateTimeEntity(Long id, LocalDate localDate, LocalTime localTime, LocalDateTime localDateTime, - OffsetTime offsetTime, OffsetDateTime offsetDateTime) { - // bug 27376147:as a result of GenerationType.Auto, - // Client is picking incorrect ID values - // this.id = id; - - this.localDate = localDate; - this.localTimeAttr = localTime; - this.localDateTime = localDateTime; - this.offsetTime = offsetTime; - this.offsetDateTime = offsetDateTime; - } - - /** - * Get entity primary key. - * - * @return primary key - */ - public Long getId() { - return id; - } - - /** - * Set entity primary key. - * - * @param id primary key to set - */ - public void setId(Long id) { - this.id = id; - } - - /** - * Get Java 8 LocalDate attribute. - * - * @return LocalDate attribute - */ - java.time.LocalDate getLocalDate() { - return localDate; - } - - /** - * Set Java 8 LocalDate attribute. - * - * @param localDate LocalDate attribute to set - */ - void setLocalDate(java.time.LocalDate localDate) { - this.localDate = localDate; - } - - /** - * Get Java 8 LocalTime attribute. - * - * @return LocalTime attribute - */ - java.time.LocalTime getLocalTime() { - return localTimeAttr; - } - - /** - * Set Java 8 LocalTime attribute. - * - * @param localTime LocalTime attribute to set - */ - void setLocalTime(java.time.LocalTime localTime) { - this.localTimeAttr = localTime; - } - - /** - * Get Java 8 LocalDateTime attribute. - * - * @return LocalDateTime attribute - */ - java.time.LocalDateTime getLocalDateTime() { - return localDateTime; - } - - /** - * Get Java 8 LocalDateTime attribute. - * - * @param localDateTime LocalDateTime attribute to set - */ - void setLocalDateTime(java.time.LocalDateTime localDateTime) { - this.localDateTime = localDateTime; - } - - /** - * Get Java 8 OffsetTime attribute. - * - * @return OffsetTime attribute - */ - java.time.OffsetTime getOffsetTime() { - return offsetTime; - } - - /** - * Set Java 8 OffsetTime attribute. - * - * @param offsetTime OffsetTime attribute to set - */ - void setOffsetTime(java.time.OffsetTime offsetTime) { - this.offsetTime = offsetTime; - } - - /** - * Get Java 8 OffsetDateTime attribute. - * - * @return OffsetDateTime attribute - */ - java.time.OffsetDateTime getOffsetDateTime() { - return offsetDateTime; - } - - /** - * Set Java 8 OffsetDateTime attribute. - * - * @param offsetDateTime OffsetDateTime attribute to set - */ - void setOffsetDateTime(java.time.OffsetDateTime offsetDateTime) { - this.offsetDateTime = offsetDateTime; - } - - @Override - public int hashCode() { - return (id != null ? id.hashCode() : 0); - } - - @Override - public boolean equals(Object object) { - if (object instanceof DateTimeEntity) { - final DateTimeEntity other = (DateTimeEntity) object; - return (this.id == null && other.id == null) || this.id != null && this.id.equals(other.id); - } else { - return false; - } - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append(this.getClass().getSimpleName()).append('['); - result.append("id=").append(id != null ? id.toString() : "null"); - result.append(','); - result.append("localDate=").append(localDate != null ? localDate.toString() : "null"); - result.append(','); - result.append("localTime=").append(localTimeAttr != null ? localTimeAttr.toString() : "null"); - result.append(','); - result.append("localDateTime=").append(localDateTime != null ? localDateTime.toString() : "null"); - result.append(','); - result.append("offsetTime=").append(offsetTime != null ? offsetTime.toString() : "null"); - result.append(','); - result.append("offsetDateTime=").append(offsetDateTime != null ? offsetDateTime.toString() : "null"); - result.append(']'); - return result.toString(); - } - -} diff --git a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/DummyEntity.java b/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/DummyEntity.java deleted file mode 100644 index 5d4b2dae9a..0000000000 --- a/jpa/spec-tests/src/main/java/ee/jakarta/tck/persistence/jpa22/datetime/DummyEntity.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package ee.jakarta.tck.persistence.jpa22.datetime; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -/** - * Dummy JPA entity used to verify schema generation process. - */ -@Entity -@Table(name = "JPA22_DT_DUMMY_ENTITY") -public class DummyEntity implements java.io.Serializable { - private static final long serialVersionUID = 22L; - - /** - * Creates an instance of dummy entity. Entity attributes are not initialized. - */ - public DummyEntity() { - } - - /** - * Creates an instance of dummy entity. Entity attributes are initialized using - * provided values. - * - * @param id dummy entity primary key - */ - public DummyEntity(Long id) { - this.id = id; - } - - /** Entity primary key. */ - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - Long id; - - /** - * Get entity primary key. - * - * @return primary key - */ - public Long getId() { - return id; - } - - /** - * Set entity primary key. - * - * @param id primary key to set - */ - public void setId(Long id) { - this.id = id; - } - - @Override - public int hashCode() { - return (id != null ? id.hashCode() : 0); - } - - @Override - public boolean equals(Object object) { - if (object instanceof DummyEntity) { - final DummyEntity other = (DummyEntity) object; - return (this.id == null && other.id == null) || this.id != null && this.id.equals(other.id); - } else { - return false; - } - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append(this.getClass().getSimpleName()).append('['); - result.append("id=").append(id != null ? id.toString() : "null"); - result.append(']'); - return result.toString(); - } - -} diff --git a/pom.xml b/pom.xml index b4882c80fb..e3c26e3ad7 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 2.0.0 - 3.1.0 + 3.2.0-M2 2.0.0 2.1.1