데이터베이스 타임 스탬프 열을 UTC Calendar (JPA)에 맵핑하고 웹 서비스 (JAX-WS)를 통해 UTC 날짜로 전달합니다.
문제
이것은 간단한 작업처럼 들립니다.
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();
}
}
그런 다음이 규칙을 모두에게 활성화하십시오 Data
S 필드 모듈의 패키지 특정 설정을 추가했습니다.
@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 마샬링이 포함됩니다.