有没有办法配置@XmlTransient JPA2.0注释,它只会在Java-Object序列化为xml时阻塞JAXB机制,而不是在传入XML转换为java对象时阻塞JAXB机制?
背景:我有一个REST api,它说XML。有一个端点可以创建一个新的Attachment对象。当我们谈到附件时,这个类中有一个byte []字段。在附件的进一步列表中,我不想传递每个附件的byte []内容。
@Entity
@XmlRootElement
public class Attachment {
private String name;
private String mimeType;
private byte[] dataPart;
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType( String mimeType ) {
this.mimeType = mimeType;
}
public byte[] getDataPart() {
return dataPart.clone();
}
public void setDataPart( byte[] dataPart ) {
this.dataPart = dataPart.clone();
}
}
因此,当我使用XmlTransient标记getDataPart()时,将忽略传入byte []的数据并将其设置为null - >它丢了。 任何人都知道如何指定XmlTransient的方向?
答案 0 :(得分:1)
我必须自己回答这个问题=) 我通过使用自定义XmlAdapter来解决这个问题,该自定义XmlAdapter将仅在一个方向上转换二进制数据。这仍然是一个黑客,我们不再使用它了。原因如下。
这是适配器:
public class DuplexBase64MarshallAdapter extends XmlAdapter<String, byte[]> {
/**
* running the adapter in half duplex mode means, the incoming data is marshaled but the
* outgoing data not.
*/
public static final boolean HALF_DUPLEX = false;
/**
* Running the adapter in full duplex means, the incoming and outgoing data is marshalled.
*/
public static final boolean FULL_DUPLEX = true;
private boolean isFullDuplexMode;
public DuplexBase64MarshallAdapter() {
this.isFullDuplexMode = HALF_DUPLEX;
}
/**
* Constructor
*
* @param fullDuplex
* use {@link #HALF_DUPLEX} or {@link #FULL_DUPLEX}
*/
public DuplexBase64MarshallAdapter( boolean fullDuplex ) {
this.isFullDuplexMode = fullDuplex;
}
@Override
public byte[] unmarshal( String v ) throws Exception {
return Base64.decode( v );
}
/**
* Return always an empty string. We do not want to deliver binary content here.
*/
@Override
public String marshal( byte[] v ) throws Exception {
if( isFullDuplexMode ) {
return Base64.encodeBytes( v );
}
return "";
}
}
实体需要使用此适配器进行注释:
@Entity
@XmlRootElement
public class Attachment {
private String name;
private String mimeType;
private byte[] dataPart;
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType( String mimeType ) {
this.mimeType = mimeType;
}
@XmlJavaTypeAdapter( DuplexBase64MarshallAdapter.class )
public byte[] getDataPart() {
return dataPart.clone();
}
public void setDataPart( byte[] dataPart ) {
this.dataPart = dataPart.clone();
}
}
此解决方案可以正常工作。但是有一个缺点:其中一个目的是不让hibernate在处理/加载附件数据时加载二进制数据。但那不是它的工作原理。在这种情况下,二进制数据由hibernate加载,因为它被发送到XMLAdapter但未转换为base64 :(
答案 1 :(得分:0)
我认为你的问题不是“是的,序列化它,而是不反序列化”,而是:传输数据客户端 - &gt;服务器,但不是服务器 - &gt;客户。您做希望您的服务器反序列化传入的byte[]
数据,对吗?你只是不想(总是?)在返回实体时将其发送出去。
如果是这种情况,您可以在发送实体之前将其设置为null。在REST资源中,执行以下操作:
@PersistenceContext(unitName = "myPersistenceUnit")
privat EntityManager em;
@Path("/upload")
@POST
public Response storeAttachment(JAXBElement<Attachment> jaxbAttachment) {
Attachment attachment = jaxbAttachment.getValue();
// store it in the DB
em.persist(attachment);
// detach it, so that modifications are no longer reflected in the database
em.detach(attachment);
// modify your guts out, it'll only affect this instance
attachment.setDataPart(null); // <-- NPE if you don't get rid of .clone() in your entity
URI newUri = ...
return Response.created(newUri).entity(attachment).build();
}
答案 2 :(得分:0)
如果您做只想序列化某些内容,但从不反序列化,请使用@XmlAccessorType(XmlAccessType.FIELD)
并仅提供@XmlElement
带注释的getter。
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Something {
public Integer foo;
public Integer getFoo() {
return foo;
}
public void setFoo(Integer foo) {
this.foo = foo;
}
@XmlElement
public Integer getBar() {
return 42;
}
}
(假设foo
设置为17),这将进入
<something>
<foo>17</foo>
<bar>42</bar>
</something>
如果你反序列化(使用相同的类定义),unmarshaller将不会设置bar
(因为它找不到setter)。
答案 3 :(得分:0)
public class HalfDuplexXmlAdapter extends XmlAdapter<String, String> {
@Override
public String unmarshal(String value) throws Exception {
return value;
}
@Override
public String marshal(String value) throws Exception {
//ignore marshall so you have half duplex
return null;
}
}
然后以这种方式使用它:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class User {
String login;
@XmlJavaTypeAdapter(HalfDuplexXmlAdapter.class)
String password;
// getters and setters
}
这样,从客户端发送到服务器的密码被序列化和反序列化,但是当用户从服务器发送到客户端时,密码未被序列化和/或反序列化,因此不会被发送(null)。