Mi solicitud, estoy usando la Primavera de Datos y JPA hibernate como proveedor de almacenar y leer datos.

He de nivel superior de clase de Entidad:

@Entity
@Getter @Setter
@Table(name = "operation")
@Inheritance(strategy = InheritanceType.JOINED)
@EqualsAndHashCode(of = {"operationId"})
public abstract class Operation implements Serializable {
public static final int OPERATION_ID_LENGTH = 20;
@Id
@Column(name = "operation_id", length = OPERATION_ID_LENGTH, nullable = false, columnDefinition = "char")
private String operationId;
@Column(name = "operation_type_code")
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private String operationTypeCode;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "begin_timestamp", nullable = false)
private Date beginTimestamp = new Date();
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "end_timestamp")
private Date endTimestamp;
@Column(name = "operation_number", length = 6, columnDefinition = "char")
private String operationNumber;
@Enumerated(EnumType.STRING)
@Column(name = "operation_status", length = 32, nullable = false)
private OperationStatus status;
@ManyToOne(optional = false)
@JoinColumn(name = "user_id")
private User user;
@ManyToOne
@JoinColumn(name = "terminal_id")
private Terminal terminal;
@Column(name = "training_mode", nullable = false)
private boolean trainingMode;
}

Para la clase heredada he correspondiente repositorio:

public interface ConcreteOperationRepository extends JpaRepository<ConcreteOperation, String> {
@Query("SELECT o FROM ConcreteOperation o WHERE o.beginTimestamp BETWEEN :from AND :to AND o.status = :status AND o.terminal.deviceId = :deviceId AND o.trainingMode = :trainingMode")
Collection<ConcreteOperation> findOperations(@Param("from") Date startDay,
@Param("to") Date endDay,
@Param("status") OperationStatus status,
@Param("deviceId") String deviceId,
@Param("trainingMode") boolean trainingMode);
}

Y tengo pruebas de integración con el siguiente método:

@Transactional
@Test
public void shouldFindOperationByPeriodAndStatusAndWorkstationId() {
Date from = new Date(Calendar.getInstance().getTime().getTime());
List<String> terminalIds = loadTerminalIds();
List<OperationStatus> typeForUse = Arrays.asList(OperationStatus.COMPLETED,
OperationStatus.LOCKED, OperationStatus.OPEN);
int countRowsForEachType = 3;
int id = 100001;
for (String terminalId : terminalIds) {
for (OperationStatus status : typeForUse) {
for (int i = 0; i < countRowsForEachType; i++) {
concreteOperationRepository.save(createConcreteOperation(status, terminalId,
String.valueOf(++id)));
}
}
}
Date to = new Date(Calendar.getInstance().getTime().getTime());
for (String terminalId : terminalIds) {
for (OperationStatus status : typeForUse) {
Collection<ConcreteOperation> operations =
concreteOperationRepository.findOperations(from, to, status, terminalId, false);
assertEquals(countRowsForEachType, operations.size());
}
}
}

Pero esta prueba falla cuando estoy usando MySql base de datos debido a un resultado vacío (pero que pasa cuando me cambie a HSQLDB)

También, esta prueba pasa si pongo retraso “Hilo.sleep(1000)” por un segundo en el comienzo de la prueba, justo después de la primera línea.

Cuando puedo ejecutar SQL desde el estado de Hibernación de registro me da el resultado correcto. Lo que está mal con mi código?

He cambiado la Fecha para LocalDateTime, pero no soluciona el problema
Trate de ZonedDateTime

OriginalEl autor Dmitry Shipaev | 2016-02-05

2 Comentarios

  1. 7

    JPA, la Date requiere de un temporal de sugerencia. Normalmente, se podría establecer la TemporalType cuando la configuración de la JPA Query parámetro:

    query.setParameter("from", from), TemporalType.TIMESTAMP);

    Con la Primavera de los Datos que usted necesita para utilizar el @Temporal anotación, por lo que su consulta se convierte en:

    @Query("SELECT o FROM ConcreteOperation o WHERE o.beginTimestamp BETWEEN :from AND :to AND o.status = :status AND o.terminal.deviceId = :deviceId AND o.trainingMode = :trainingMode")
    Collection<ConcreteOperation> findOperations(
    @Param("from") @Temporal(TemporalType.TIMESTAMP) Date startDay,
    @Param("to") @Temporal(TemporalType.TIMESTAMP) Date endDay,
    @Param("status") OperationStatus status,
    @Param("deviceId") String deviceId,
    @Param("trainingMode") boolean trainingMode
    );
    He añadido la anotación @Temporales(TemporalType.Fecha y hora) antes de la fecha. Pero esto no ha dado ningún resultado
    Entonces mejor registro de la consulta SQL con parámetros mediante P6Spy
    Todo parece correcto. He ejecutado la consulta del cliente y todo está ok (concreop0_1_.begin_timestamp entre ‘2016-02-07 11:44:21’ y ‘2016-02-07 11:44:22’) y concreop0_1_.training_mode=false
    Así que si la consulta está bien, es que todavía no funciona?
    No, no de trabajo, mientras que raw sql es correcto. Sólo funciona si puedo configurar el pequeño retraso, después de definir la Fecha de. Pero si yo no se hacer este resultado está vacía.

    OriginalEl autor Vlad Mihalcea

  2. 0

    Me di cuenta de mi problema. El problema era debido a la diferencia de precisión entre el tipo de campo en MySql (por defecto marca de tiempo de corte de la precisión de milisegundos) y Java fecha (con milisegundos)
    He alterado mi mesa:

    ALTER TABLE transaction modify end_timestamp TIMESTAMP(6)

    y que se resolvió mi problema.

    ¿Que quiere decir “microsegundos” para MySQL?
    El java.marco de tiempo construido en Java 8 y más tarde no tiene ningún tipo de problema, manejo de resolución de nanosegundos (hasta 9 dígitos de una fracción de segundo). Si utiliza java.sql.Timestamp y java.time.Instant usted no tendrá ningún problema con la pérdida de datos. Evitar el notoriamente molesto java.util.Fecha/.Calendario de clases.
    Sí, gracias por la corrección. Me refería a “microsegundos”. Pero microsegundos fueron cortadas por MySql. Por ejemplo: cuando tengo que insertar “2016-02-09 08:11:37.567” esta marca de tiempo insertado en MySql como “2016-02-09 08:11:37”.

    OriginalEl autor Dmitry Shipaev

Dejar respuesta

Please enter your comment!
Please enter your name here