Hibernate 식별 데이터베이스 특유 필드 실례 상세 설명

Hibernate 식별 데이터베이스 특유 필드 실례 상세 설명
선언:
Hibernate 는 대부분의 상용 데이터베이스 데이터 형식 에 내장 지원 을 제 공 했 지만 일부 데이터베이스 의 전속 필드 에 대한 지원 이 부족 합 니 다.이런 특수 데이터 유형 은 흔히 일반적인 데이터 유형 보다 더 좋 은 데이터 표 현 력 을 제공 하고 우리 의 업무 장면 에 더욱 부합된다.예 를 들 어 PostgreSQL 의 Interval 형식 은 한 시간 대의 데 이 터 를 편리 하 게 저장 할 수 있 습 니 다.본 고 는 Interval 형식 지원 을 추가 하 는 것 을 예 로 들 어 Hibernate 에 특유 의 데이터 형식 지원 을 추가 하 는 방법 을 설명 한다.
Hibernate 는 풍부 한 데이터 형식 지원 을 제공 하지만 일부 데이터베이스 전용 데이터 형식 에 대한 지원 은 한계 가 있 습 니 다.예 를 들 어 PostgreSQL 의 Interval 형식 은'시간 대'데 이 터 를 저장 하 는 데 매우 편리 하 다.
개발 과정 에서 우 리 는 Interval 유형 을 자바 8 의 Duration 유형 으로 비 추 기 를 기대한다.그러나 Hibernate 의 기본 Duration 형식 에 대한 맵 은 데이터베이스 에 직접 비 치 는 BigInt 형식 으로 나 초 값 을 직접 저장 합 니 다.분명히 Interval 형식 을 직접 지원 하지 않 는 데이터 베 이 스 는 비교적 적합 하지만 우 리 는 데이터 베 이 스 를 직접 반영 하 는 Interval 유형 을 기대 합 니 다.
이 를 위해 서 는 두 가지 데이터 형식(자바 세계 의 Duration 과 Db 세계 의 Interval)에 대한 Hibernate 의 매 핑 관 계 를 조정 해 야 합 니 다.
다행히도 하 이 버 네 이 트 는 데이터 형식의 매 핑 을 실현 할 수 있 는 매우 편리 한 방법 을 제공 했다.
이 를 위해 서 는 org.hibenate.usertype.User Type 인 터 페 이 스 를 실현 하 는 클래스 가 필요 합 니 다.
Hibernate 의 사용자 정의 형식(UserType)
User Type 은 Hibernate 가 제공 하 는 사용자 정의 데이터 형식의 인터페이스 입 니 다.모든 사용자 정의 데 이 터 는 이 인 터 페 이 스 를 실현 하거나 org.hibenate.usertype 에서 정의 하 는 인터페이스 에서 적당 한 인 터 페 이 스 를 선택해 야 합 니 다.
우리 의 장면 이 비교적 간단 하 다 는 것 을 감안 하여 User Type 을 직접 실현 하면 수 요 를 만족 시 킬 수 있다.이 인 터 페 이 스 는 다음 과 같은 방법 을 제공 합 니 다.
assemble(Serializable cached, Object owner)
     직렬 화 에서 대상 을 재 구축 하 다.
deepCopy(Object value)
      깊이 던 전 을 되 돌려 줍 니 다.
disassemble(Object value)
     대상 의 직렬 화 데 이 터 를 변환 합 니 다.
equals(Object x, Object y)
     두 맵 의 데이터 가 같 는 지 되 돌려 줍 니 다.
hashCode(Object x)
      대상 의 해시 가 져 오기.
isMutable()
      대상 이 가 변 형식 인지 되 돌려 줍 니 다.
nullSafeGet(ResultSet rs, String[] names, Object owner)
      데이터베이스 형식의 데이터 에서 대응 하 는 자바 대상 을 되 돌려 줍 니 다.핵심 실현 방법
nullSafeSet(PreparedStatement st, Object value, int index)
       자바 대상 에서 대응 하 는 데이터베이스 형식의 데 이 터 를 되 돌려 줍 니 다.핵심 실현 방법
replace(Object original, Object target, Object owner)
       합병 기간 에 실체의 목표 값(target)을 원시 값(original)으로 대체 합 니 다.
returnedClass()
      null SafeGet 이 되 돌아 오 는 클래스 입 니 다.
sqlTypes()
       대응 하 는 데이터베이스 형식 을 되 돌려 줍 니 다.
실례

package framework.postgresql;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
import org.postgresql.util.PGInterval;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Duration;

/**
 * PostgreSql Inteval   java.time.Duration  
 *         1  (30 )   
 * <p>
 *     :
 *        
 * \@TypeDef(name="interval", typeClass = IntervalType.class)
 *         :
 * \@Type(type = "interval")
 * <p>
 * http://stackoverflow.com/questions/1945615/how-to-map-the-type-interval-in-hibernate/6139581#6139581
 *
 * @version 1.0
 * @since 1.0
 */
public class IntervalType implements UserType {

 public Object assemble(Serializable cached, Object owner) throws HibernateException {
  return cached;
 }

 public Object deepCopy(Object value) throws HibernateException {
  return value;
 }

 public Serializable disassemble(Object value) throws HibernateException {
  return (Serializable) value;
 }

 public boolean equals(Object arg0, Object arg1) throws HibernateException {
  return arg0 != null && arg1 != null && arg0.equals(arg1) || arg0 == null && arg1 == null;
 }

 public int hashCode(Object object) throws HibernateException {
  return object.hashCode();
 }


 @Override
 public Object nullSafeGet(ResultSet resultSet, String[] names, SharedSessionContractImplementor sessionImplementor, Object o) throws HibernateException, SQLException {
  String interval = resultSet.getString(names[0]);
  if (resultSet.wasNull() || interval == null) {
   return null;
  }
  PGInterval pgInterval = new PGInterval(interval);

  return getDuration(pgInterval);
 }

 @Override
 public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor sessionImplementor) throws HibernateException, SQLException {
  if (value == null) {
   st.setNull(index, Types.OTHER);
  } else {
   //this http://postgresql.1045698.n5.nabble.com/Inserting-Information-in-PostgreSQL-interval-td2175203.html#a2175205
   Duration duration = (Duration) value;
   st.setObject(index, getInterval(duration), Types.OTHER);
  }
 }

 public static Duration getDuration(PGInterval pgInterval) {
  return Duration.ofSeconds(pgInterval.getDays() * 24 * 3600 +
    pgInterval.getHours() * 3600 +
    pgInterval.getMinutes() * 60 +
    (int) pgInterval.getSeconds());
 }

 private static PGInterval getInterval(Duration value) {
  long seconds = value.getSeconds();
  int days = (int) (seconds / (24 * 3600));
  seconds -= days * 24 * 3600;
  int hours = (int) (seconds / 3600);
  seconds -= hours * 3600;
  int minutes = (int) (seconds / 60);
  seconds -= minutes * 60;
  seconds = Math.abs(seconds);
  return new PGInterval(0, 0, days, hours, minutes, seconds);
 }


 public boolean isMutable() {
  return false;
 }


 public Object replace(Object original, Object target, Object owner) throws HibernateException {
  return original;
 }

 public Class returnedClass() {
  return Duration.class;
 }

 public int[] sqlTypes() {
  return new int[]{Types.OTHER};
 }

}

사용자 정의 형식 사용
이로써 우 리 는 자신의 데이터 형식 을 정의 했다.히 버 네 이 트 는 아직 어떻게 사용 해 야 할 지 모 르 겠 어 요.이 를 위해 서 는 Entity 에서 TypeDef 주 해 를 사용 하고 속성 적 으로 Type 주 해 를 사용 해 야 합 니 다.
예 를 들 면:

...
@Entity
@TypeDef(name = "interval", typeClass = IntervalType.class)
public class PaperStatis implements Serializable {
...
 @Column(name = "avg_duration")
 @Type(type = "interval")
 public Duration getAvgDuration() {
  return this.avgDuration;
 }
...
}
읽 어 주 셔 서 감사합니다. 여러분 에 게 도움 이 되 기 를 바 랍 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기