2017-12-04 1 views
0

Hibernate는 이름 (어쩌면 열 또는 주석이 첨부 된 클래스)을 기반으로 쿼리 매개 변수에 대한 데이터 유형을 자동으로 가정한다는 것에 주목했습니다. 유닉스 타임 스탬프를 MySQL 데이터베이스의 BIGINT 컬럼에 저장하려고합니다. 이름이 데이터베이스와 나의 (JPA) 주석 클래스에서 타임 스탬프가 될 때, Hibernate는 자동적으로 임시 값이라는 것을 가정하므로 쿼리에서이 컬럼에 긴 값을 바인드하려고 할 때 예외가 발생한다. Hibernate는 java.util.Date를 기대한다. 데이터베이스에서이 열의 이름을 'foobar'로 바꾸면 모든 것이 예상대로 작동합니다. Hibernate가 그런 어리석은 가정을하는 것을 어떻게 멈출 수 있습니까?Hibernate가 이름에 기반한 매개 변수 바인딩을위한 데이터 타입을 가정하지 못하게하는 방법

편집 :

DB 테이블 :

CREATE TABLE candle 
(
    `open` decimal(25,15) NOT NULL, 
    `high` decimal(25,15) NOT NULL, 
    `low` decimal(25,15) NOT NULL, 
    `close` decimal(25,15) NOT NULL, 
    `volume` decimal(15,2) NOT NULL, 
    `symbol` varchar(255) NOT NULL, 
    `exchange` varchar(255) NOT NULL, 
    `timestamp` bigint NOT NULL, 
    `width` bigint NOT NULL, 
    PRIMARY KEY(`symbol`, `exchange`, `timestamp`, `width`), 
    KEY idx_symbol (`symbol`), 
    KEY idx_exchange (`exchange`), 
    KEY idx_timestamp (`timestamp`), 
    KEY idx_width (`width`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

JPA 클래스 :

@Entity(name="candle") 
public class JpaCandle { 

    @EmbeddedId 
    private Key id; 

    @Column 
    private BigDecimal open; 

    @Column 
    private BigDecimal high; 

    @Column 
    private BigDecimal low; 

    @Column 
    private BigDecimal close; 

    @Column 
    private BigDecimal volume; 

    public Key getId() { 
     return id; 
    } 

    @Embeddable 
    public static class Key implements Serializable { 
     @Column 
     private String symbol; 

     @Column 
     private String exchange; 

     @Column 
     private long timestamp; 

     @Column 
     private long width; 
    } 
} 

검색어 :

TypedQuery<JpaCandle> q = em.createQuery("FROM candle WHERE symbol = :symbol AND width = :width AND timestamp >= :from AND timestamp <= :until ORDER BY timestamp ASC", JpaCandle.class); 
q.setParameter("from", from.toEpochMilli()); 
q.setParameter("until", until.toEpochMilli()); 
q.setParameter("symbol", symbol); 
q.setParameter("width", width.getSeconds()); 
List<JpaCandle> jpaCandles = q.getResultList(); 
+1

일부 코드를 증명 자료로 제공 할 수 있습니까? 가능한 모든 주석이있는 타임 스탬프를 포함하는 필드를 의미하는 모든 경우에 minimun? 또한 바람직하게는 각 사례에 대한 예외/오류도 있습니까? – pirho

+0

java.lang.IllegalArgumentException으로 실패한 관련 코드를 추가했습니다. 매개 변수 값 [1512662224763]이 예상 유형 [java.util.Date (n/a)]과 일치하지 않습니다. 내가 말했듯이, 내가 데이터베이스, JPA 클래스 및 쿼리에서 다른 것으로 timestamp의 이름을 변경하면 예상대로 작동합니다. – henrik

+0

v.ladynev에는 요점이 있다고 생각합니다. 적어도 JPQL에서 "timestamp"와 같은 "timestamp"를 "escaping"시도하는 것이 가능할까요? 이름이 바뀌 었는지 확인하십시오. – pirho

답변

0

TIMESTAMP는 MySQL의에서 열 유형입니다. 열에 이러한 이름을 사용하지 않는 것이 좋습니다. 아마도 MySQL은 Date과 같은 값의 유형을 반환합니다.

+0

이름들은 Hibernate의 MySQL 사투리에 의해 적절히 이스케이프되어야한다. 또한 컬럼은 BIGINT로 정의됩니다. 이 이상한 동작은 MySQL이 아닌 Hibernate에서 유래 된 것입니다. BTW. 매우 유사한 설정은 'timestamp'라는 이름에 문제없이 다른 영속성 단위에서 작동합니다. 나는 이유를 모른다. 나는 여러 번 모든 것을 비교했고 차이점을 발견 할 수 없었다. – henrik

+0

@henrik "이름들은 Hibernate의 MySQL 사투리에 의해 적절히 이스케이프되어야한다."나는 그렇게 생각하지 않는다. 로그에서 Hibernate에 의해 SQL이 생성되었는지 확인하십시오. –

+0

MySQL 쿼리 로그를 확인했습니다 ... 쿼리가 로그에 나타나지 않습니다. Hibernate는 실행 전에 실패한다. 예외는 다음과 같습니다 : java.lang.IllegalArgumentException : 매개 변수 값 [1512662574127]이 예상 유형과 일치하지 않습니다. [java.util.Date (n/a)] – henrik

관련 문제