簡體   English   中英

使用JAXB將子類實例作為超類傳遞

[英]Using JAXB to pass subclass instances as superclass

我所擁有的是一組表示消息類型的Java類(接近25個)。 它們都繼承自我想抽象的Message類。 每種消息類型都會在Message超類提供的集合中添加一些其他字段。

我正在使用RESTeasy實現一些RESTful Web服務,並希望具有以下方法:

public Response persist(Message msg) {
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    try {
        em.persist(msg);
    } catch (Exception e) {
        e.printStackTrace();
    }
    tx.commit();
    em.close();
    return Response.created(URI.create("/message/" + msg.getId())).build();
}

而不是使用25種單獨的persist方法,每種方法都針對特定的消息類型進行了調整。

目前,我已經為Message類添加了如下注釋:

@MappedSuperclass
@XmlRootElement(name = "message")
public abstract class Message implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Integer id;
    @Embedded
    Header header;
    @Embedded
    SubHeader subHeader;

然后,我的子類如下所示:

@Entity
@XmlRootElement(name="regmessage")
@XmlAccessorType(XmlAccessType.FIELD)
public class REGMessage extends Message {

    @XmlElement(required = true)
    int statusUpdateRate;
    @XmlElement(required = true)
    int networkRegistrationFlag;

這樣會創建一個看起來應該工作的架構,但是在持久化操作期間在服務器端看到的只是一個Message對象(該子類型已完全丟失,或者至少沒有被整理回其正確的子類型)。 在客戶端,要調用該方法,我需要這樣做:

REGMessage msg = new REGMessage();
// populate its fields
Response r = client.createMessage(msg);

我正在嘗試的可能嗎? 我需要使用什么JAXB魔術來使轉換按應有的方式發生-即,將Java中的所有內容都視為一條消息,以減少方法數量,但仍保留所有特定於子類型的信息?


多虧了Blaise的博客提示,現在看來,它正在全面工作。 這是我所擁有的,並且確實有效:

//JAXB annotations
@XmlRootElement(name="message")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso(REGMessage.class)
//JPA annotations
@MappedSuperclass
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @XmlAttribute
    private Integer id;

    private JICDHeader header;
    private int subheader;

    @XmlAnyElement
    @Transient
    private Object body;

今天早上我遇到的問題之一是Hibernate的一個不正確的錯誤,即列數不匹配。 一旦我意識到“ body”已映射到表中,就將其標記為瞬態和瞧!

@XmlRootElement(name="regmessage")
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class REGMessage extends Message {

    private int field1;
    private int field2;

現在,通過此代碼生成的唯一表是regmessage表。 在RESTeasy方面:

@Path("/messages")
public class MessageResource implements IMessageResource {

    private EntityManagerFactory emf;
    private EntityManager em;

    Logger logger = LoggerFactory.getLogger(MessageResource.class);

    public MessageResource() {
        try {
            emf = Persistence.createEntityManagerFactory("shepherd");
            em = emf.createEntityManager();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @POST
    @Consumes("application/xml")
    public Response saveMessage(Message msg) {

        System.out.println(msg.toString());

        logger.info("starting saveMessage");
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {
            em.persist(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }

        tx.commit();
        em.close();
        logger.info("ending saveMessage");

        return Response.created(URI.create("/message/" + msg.getId())).build();
    }
}

這實現了一個接口:

@Path("/messages")
public interface IMessageResource {

    @GET
    @Produces("application/xml")
    @Path("{id}")
    public Message getMessage(@PathParam("id") int id);

    @POST
    @Consumes("application/xml")
    public Response saveMessage(Message msg) throws URISyntaxException;

}

編組和解組工作按預期進行,並且持久性屬於子類的表(並且根本沒有超類表)。

我確實看到了Blaise關於JTA的說明,在我完全充實了Message&REGMessage類后,我可能會嘗試將其引入。

您是否嘗試過將以下內容添加到您的消息類別中? @XmlSeeAlso批注將使JAXBContext知道子類。

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;

@XmlRootElement
@XmlSeeAlso(RegMessage.class)
public abstract class Message {

    Integer id;

}

替代策略:

這是我幫助人們使用的策略的鏈接:

本質上,您有一個消息對象和多個單獨的消息有效負載。 消息和有效負載之間的關系通過@XmlAnyElement批注處理。

交易處理注意事項

我注意到您正在處理自己的交易。 您是否考慮過將JAX-RS服務實現為會話bean,並利用JTA進行事務處理? 有關示例,請參見:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM