데이터베이스 타임 스탬프 열을 UTC Calendar (JPA)에 맵핑하고 웹 서비스 (JAX-WS)를 통해 UTC 날짜로 전달합니다.

StackOverflow https://stackoverflow.com/questions/1821104

  •  10-07-2019
  •  | 
  •  

문제

이것은 간단한 작업처럼 들립니다.
DB에서 UTC 타임 스탬프 값을 얻고 웹 서비스를 통해 UTC 날짜로 전달하십시오.

타임 스탬프 열 날짜 _column이 있으며 UTC 시간대에 시간을 저장합니다.

JPA와 함께 우리는이 시간을 얻습니다

@Column(name = "DATE_COLUMN")
private java.sql.Timestamp dateValue;

UTC (JAX-WS 2.0)의 웹 서비스를 통해이 시간을 통과해야하므로 GetDate 및 SetDate 방법이 있습니다.
우리는 GetDate에 관심이 있습니다.

public Calendar getDate()
{
   Calendar calendar = Calendar.getInstance(utcTimeZone);
   calendar.setTimeInMillis(dateValue.getTime());

   return calendar;
}

이것은 당신이 생각할 수있는대로 작동하지 않습니다.
그리고 이것은 응용 프로그램의 기본 시간대가 'UTC'가 아니기 때문입니다.

설명을위한 예입니다.
date_column의 값은 "30.11.09 16 : 34 : 48,833045000"과 같습니다.
차이는 2 시간입니다. 그리고 이것은 내 기본 시간대가 "유럽/헬싱키"이기 때문입니다.

'date_column'을 매핑하려면 동일한 문제 Calendar

@Column(name = "DATE_COLUMN")
@Temporal(TemporalType.TIMESTAMP)
private Calendar dateValue;

public Calendar getDate()
{
   calendar.setTimeZone(utcTimeZone);
   return calendar;
}

응용 프로그램의 시간대가 솔루션처럼 보이지 않기 때문에 변경하고 싶지 않습니다.

지금까지 우리는 두 가지 옵션 만 있습니다.

첫 번째. 응용 프로그램의 시간대와 UTC 사이의 오프셋을 계산하고 캘린더에서 자동 뺄셈 후 수동으로 추가하십시오.

public Calendar getDate()
{
   Calendar calendar = Calendar.getInstance(utcTimeZone);
   calendar.setTimeInMillis(dateValue.getTime());

   int offset = TimeZone.getDefault().getOffset(dateValue.getTime());

   calendar.add(Calendar.MILLISECOND, offset);

   return calendar;
}

. 날짜 value를 통과합니다 Long 웹 서비스를 통해. WSDL에서 실제 유형의 필드를 잃는 것을 제외하고는 나쁘지 않습니다.

내 상상의 해결책은입니다

@Column(name = "DATE_COLUMN")
@Temporal(type = TemporalType.TIMESTAMP, timezone = 'UTC')
private Calendar dateValue;

그러나 나는 어딘가에 실제가 있다고 생각하는 경향이 있습니다. 그리고 나는 당신이 그것을 지적 할 수 있기를 바랍니다.

도움이 되었습니까?

해결책

우리는 다음 솔루션을 사용하기로 결정했습니다.
사용 Date 데이터베이스에서 날짜를 검색합니다. 그 이유는 Date TimeZoneless 유형입니다.

@Column(name = "DATE_COLUMN")
@Temporal(TemporalType.TIMESTAMP)
private Date dateValue;

public Date getDate()
{
   return dateValue;
}

UTC (JAX-WS)의 WebService를 통해 보내려면 UtcTimestampAdapter 마샬링 단계에서 구역을 응용 프로그램의 기본값에서 UTC로 변경합니다.

public class UtcTimestampAdapter extends XmlAdapter<XMLGregorianCalendar, Date>
{
   @Override
   public XMLGregorianCalendar marshal(Date date) throws Exception
   {
      GregorianCalendar calendar = new GregorianCalendar();
      calendar.setTime(date);

      DatatypeFactory dataTypeFactory = DatatypeFactory.newInstance();
      XMLGregorianCalendar xmlCalendar = 
         dataTypeFactory.newXMLGregorianCalendar(calendar);

      //Reset time zone to UTC
      xmlCalendar.setTimezone(0);

      return xmlCalendar;
   }

   @Override
   public Date unmarshal(XMLGregorianCalendar calendar) throws Exception
   {
      return calendar.toGregorianCalendar().getTime();
   }
}

그런 다음이 규칙을 모두에게 활성화하십시오 DataS 필드 모듈의 패키지 특정 설정을 추가했습니다.

@XmlJavaTypeAdapter(value = UtcTimestampAdapter.class, type = Date.class)
@XmlSchemaType(name = "dateTime", type = XMLGregorianCalendar.class)
package com.companyname.modulename;

그게 다야. 이제 우리는 모든 논리를 한 곳에 캡슐화하는 일반적인 솔루션을 가지고 있습니다. 다른 모듈에서 웹 서비스를 통해 TimeZoness Dates를 UTC로 보내려면 특정 패키지에 주석을 달 것입니다.

다른 팁

UTC 타임 존에서 실행하기 위해 Java 프로세스가 필요한 경우 가장 쉬운 방법은 다음 JVM 매개 변수를 추가하는 것입니다.

-Duser.timezone=UTC

TimeZone.setDefault(TimeZone.getTimeZone("UTC")); 전체 JVM에 영향을 미치는 것 같습니다.

현지 시간을 기대하면 다른 응용 프로그램이 실패합니다.

또 다른 솔루션은 응용 프로그램의 기본 시간대를 @StartupBean:

import java.util.TimeZone;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Startup
@Singleton
public class StartupBean {

    @PostConstruct
    public void initializeTheServer() {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }
}

그때부터 날짜 객체의 모든 해석은 UTC를 기반으로합니다. 여기에는 XML 마샬링이 포함됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top