当前位置: 首页 > 面试题库 >

使用JAXB将子类实例作为超类传递

施旭东
2023-03-14
问题内容

我所拥有的是一组表示消息类型的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;

}

替代策略:

这是我帮助人们使用的策略的链接:

  • http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html

本质上,您有一个消息对象和多个单独的消息有效负载。消息和有效负载之间的关系通过@XmlAnyElement批注处理。

交易处理注意事项

我注意到您正在处理自己的交易。您是否考虑过将JAX-RS服务实现为会话bean,并利用JTA进行事务处理?有关示例,请参见:

  • http://bdoughan.blogspot.com/2010/08/creating-restful-web-service-part-45.html


 类似资料:
  • 问题内容: 是否可以将带有JAXB注释的类实例封送 为其超类 (这也是一个具有JAXB注释的类)? 和扩展类型: 因此,如果出现这种情况: 然后我想将 实例 b 作为 BenmaningTYPE封送, 以获取 而且 不是 : 如果可能的话,元帅的调用会是什么样子? 问题答案: 我没有检查过,但我会先尝试: 如果要从XML模式生成类,请同时检查copyable插件。您可以将数据从的实例复制到该实例并

  • 问题内容: 我一直在尝试JAXB教程,并设法使代码能够从Java对象生成XML文件,然后能够使用XML生成Java对象。目前,它读取同一类的多个实例以创建一个类似于以下内容的XML文件 我希望能够使用JAXB技术来处理子类。例如:说我有一个Car,Van和Bicycle对象,它们是Vehicle的子类。我是否可以操纵我的JAXB类来编写一个会产生类似结果的XML文件?我在下面提供了我正在使用的代码

  • 假设我有以下代码 然而,现在我希望能够将一个超类对象传递给子类构造函数。我该怎么做? 基本上,我想这样做。。。 但是如果超类更复杂,我不想在super()调用中添加每个值。相反,我只想传入一个已经存在的对象,并将其用作超类。 我想这么做。。。 但我不确定这是否被允许? 如果我在超类定义中添加一个构造函数,似乎我可以完成上面的工作。但那会是什么样子呢?

  • 是的数组列表。有两个子类,比如。这里我试图将一个投射物传递到另一个函数中。 我的问题是,当将的一个实例传递到此函数中时,它不是转到而是转到。如何让对象作为其特定子类的实例传递?

  • 问题内容: 考虑这种情况。 有地块,有的是住宅用地,有的是商业用地。 也有所有者。但是所有者只能购买一块土地,并且可以是住宅或商业用地。 所以,这是我的代码。 一切运作良好,但是当我打电话 ,我期待或实例,这样,我可以通过采取适当的操作符。但是它不能同时满足这两个条件! 我究竟做错了什么? 问题答案: 您没有使用多态,它在JPA环境中的危害更大。 观察到此行为的原因是由于Hibernate使用了代

  • 我理解超类/子类之间的关系以及强制转换是如何工作的。但是,我的问题是,如果知道中间有一个类,你能把一个超类转换成一个特定的子类吗?例如,如果我有一个动物类对象包含一个BigDog对象,我可以将该对象强制转换为Dog吗?如果BigDog中有Dog中不存在的方法怎么办? 简而言之,你当然可以说超类对象是子类对象,但为什么你可以反转呢? 转念一想, Java在调用方法时检查的是:引用(DOG)是否有引用