如何使用 JPA 保留 XMLGregorianCalendar?
How to persist XMLGregorianCalendar with JPA?
这是我的:
@XmlSchemaType(name = "dateTime")
@Column(name = "expiry-date", nullable = false)
protected XMLGregorianCalendar expiryDate;
抛出以下异常:
org.hibernate.MappingException: Could not determine type for: javax.xml.datatype.XMLGregorianCalendar
谢谢
JPA 不支持 XMLGregorianCalendar
,您可以使用 java.util.Date
或 java.util.Calendar
(解释为 here)。
也许您可以看一下项目 Hyperjaxb3(为 JAXB 对象提供关系持久性)。
Here 解释了如何处理时间属性:
Temporal properties (typed xsd:dateTime, xsd:date, xsd:time and so on)
will be mapped as temporal JPA properties. Hyperjaxb3 will choose
temporal type as TIMESTAMP, DATE or TIME depending on the XML Schema
type of the temporal property. Temporal properties are typically
mapped onto XMLGregorianCalendar which is not supported by JPA - and
therefor must be wrapped:
<xs:element name="dateTime" type="xs:dateTime" minOccurs="0"/>
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar dateTime;
@Transient
public XMLGregorianCalendar getDateTime() {
return dateTime;
}
public void setDateTime(XMLGregorianCalendar value) {
this.dateTime = value;
}
@Basic
@Column(name = "DATETIMEITEM")
@Temporal(TemporalType.TIMESTAMP)
public Date getDateTimeItem() {
return XmlAdapterUtils.unmarshall(XMLGregorianCalendarAsDateTime.class, this.getDateTime());
}
public void setDateTimeItem(Date target) {
setDateTime(XmlAdapterUtils.marshall(XMLGregorianCalendarAsDateTime.class, target));
}
另一种方法是编写您自己的解决方案,执行一些转换而不是尝试保留您的 JAXB 对象。
您可以在不使用任何额外框架的情况下简单地做到这一点。例如:
@Transient
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar expiryDate;
@Column(name = "expiry-Date", nullable = false)
public Calendar getExpiryDateToCalendar() {
return new GregorianCalendar(expiryDate.getYear(), expiryDate.getMonth(), expiryDate.getDay());
}
这是一个工作示例。您还应该注意代码中的月份,因为在 XMLGregorianCalendar 中月份定义为从 1 到 12,但是在日历中 - 从 0 到 11。
@Entity
@Access(AccessType.FIELD)
@Table(name="test_my_entity")
public class MyEntity {
@Id
@GeneratedValue
private Long id;
@XmlAttribute(name = "name")
@Transient
protected String name;
@XmlSchemaType(name = "dateTime")
@Transient
protected XMLGregorianCalendar myXMLDate;
@Transient
private Calendar calendarDate;
@Access(AccessType.PROPERTY)
@Column(name = "calendar_date")
private Calendar getCalendarDate() {
return new GregorianCalendar(myXMLDate.getYear(), myXMLDate.getMonth()-1, myXMLDate.getDay());
}
@Access(AccessType.PROPERTY)
@Column(name = "my_str_name")
public String getName() {
return "My string";
}
//...setters here
public MyEntity() {
}
}
这是我的:
@XmlSchemaType(name = "dateTime")
@Column(name = "expiry-date", nullable = false)
protected XMLGregorianCalendar expiryDate;
抛出以下异常:
org.hibernate.MappingException: Could not determine type for: javax.xml.datatype.XMLGregorianCalendar
谢谢
XMLGregorianCalendar
,您可以使用 java.util.Date
或 java.util.Calendar
(解释为 here)。
也许您可以看一下项目 Hyperjaxb3(为 JAXB 对象提供关系持久性)。 Here 解释了如何处理时间属性:
Temporal properties (typed xsd:dateTime, xsd:date, xsd:time and so on) will be mapped as temporal JPA properties. Hyperjaxb3 will choose temporal type as TIMESTAMP, DATE or TIME depending on the XML Schema type of the temporal property. Temporal properties are typically mapped onto XMLGregorianCalendar which is not supported by JPA - and therefor must be wrapped:
<xs:element name="dateTime" type="xs:dateTime" minOccurs="0"/>
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar dateTime;
@Transient
public XMLGregorianCalendar getDateTime() {
return dateTime;
}
public void setDateTime(XMLGregorianCalendar value) {
this.dateTime = value;
}
@Basic
@Column(name = "DATETIMEITEM")
@Temporal(TemporalType.TIMESTAMP)
public Date getDateTimeItem() {
return XmlAdapterUtils.unmarshall(XMLGregorianCalendarAsDateTime.class, this.getDateTime());
}
public void setDateTimeItem(Date target) {
setDateTime(XmlAdapterUtils.marshall(XMLGregorianCalendarAsDateTime.class, target));
}
另一种方法是编写您自己的解决方案,执行一些转换而不是尝试保留您的 JAXB 对象。
您可以在不使用任何额外框架的情况下简单地做到这一点。例如:
@Transient
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar expiryDate;
@Column(name = "expiry-Date", nullable = false)
public Calendar getExpiryDateToCalendar() {
return new GregorianCalendar(expiryDate.getYear(), expiryDate.getMonth(), expiryDate.getDay());
}
这是一个工作示例。您还应该注意代码中的月份,因为在 XMLGregorianCalendar 中月份定义为从 1 到 12,但是在日历中 - 从 0 到 11。
@Entity
@Access(AccessType.FIELD)
@Table(name="test_my_entity")
public class MyEntity {
@Id
@GeneratedValue
private Long id;
@XmlAttribute(name = "name")
@Transient
protected String name;
@XmlSchemaType(name = "dateTime")
@Transient
protected XMLGregorianCalendar myXMLDate;
@Transient
private Calendar calendarDate;
@Access(AccessType.PROPERTY)
@Column(name = "calendar_date")
private Calendar getCalendarDate() {
return new GregorianCalendar(myXMLDate.getYear(), myXMLDate.getMonth()-1, myXMLDate.getDay());
}
@Access(AccessType.PROPERTY)
@Column(name = "my_str_name")
public String getName() {
return "My string";
}
//...setters here
public MyEntity() {
}
}