在JAX-RS中序列化一个java.util.list

3

我有这本课程教材:

@Entity
@Table(name = "books")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType

public class Book {
    @Id
    @XmlAttribute
    private String isbn;

    private String title;
    private String authors;
    private int year;

    @OneToMany(mappedBy="reservedBook")
    private List<Reservation> bookReservations;

    //Getters, setters, addReservation, remove Reservation
        ......................
}

然后,我有一个预订类。
@Entity
@Table(name = "reservations")
@XmlRootElement

public class Reservation {

    private String username;
    private String isbn;
    @Temporal(TemporalType.DATE)
    private Date date;

    @ManyToOne
    @JoinColumn(name = "isbn")
    private Book reservedBook;

    @ManyToOne
    @JoinColumn(name = "username")
    private User userWhoReserved;

        //Getters and setters

        ...........
 }

在资源类中,我尝试像这样获取特定的书籍:
@GET
@Path("/{isbn}")
@Produces(MediaType.TEXT_XML)
public Book getBookByIsbn(@PathParam("isbn") String isbn) {

    Book book = entityManager.find(Book.class, isbn);

    if (book != null) {
        return book;

    }

}

现在,它不序列化字段List bookReservations。我尝试了很多在网上找到的想法,比如用@XmlElement注释列表的getter或在其他地方使用其他注释(我现在不记得了),但都没用。
编辑:这就是响应的样子:
<book isbn="3333333333">
    <title>Mere Christianity</title>
    <authors>C. S. Lewis</authors>
    <year>2000</year>
</book>

但我也想显示保留内容。
有什么解决方案吗? 谢谢! Sorin

1
你尝试在OneToMany和ManyToOne注释中添加fetch = FetchType.EAGER了吗? - Thinhbk
@Think: 我已经解决了这个问题...我已经发布了解决方案。 - Sorin Adrian Carbunaru
5个回答

3

我认为问题可能出在列表bookReservations为空值。

class A{

    private List<String> someList = new ArrayList<String>();

    @XmlElement(name = "some-tag")
    public List<String> getList() {
        return someList;
    }

    public void setSomeList(List<String> someOtherList) {
        this.someList = someOtherList;
    }
}

我每天都使用这段代码,对我来说很有效(忽略我没有提供的其他注释)。

我曾经遇到过问题,但只发现由于某些原因列表为空,因此未进行序列化。 通过在setter方法处进行调试,尝试检查JAXB是否设置了列表。


是的,它为null,但是因为EntityManager.find()方法找不到它... - Sorin Adrian Carbunaru
你通常使用entityManager.find()还是查询来获取结果?似乎find()方法没有提取预订并将其放入我的Book对象中... - Sorin Adrian Carbunaru
你需要配置 @OneToMany(fetch=FetchType.EAGER,mappedBy="reservedBook") private List<Reservation> bookReservations; - Narendra Pathai
我按照我发布的答案去做了,现在可以运行了...但是,如果我按照你说的去做,能够用于entityManager.find()吗? - Sorin Adrian Carbunaru
是的,它应该可以工作。如果您没有将其配置为EAGER,则不会获取关联记录。 - Narendra Pathai
显示剩余2条评论

1
我的猜测是这是懒加载的问题,你可以在OneToMany和ManyToOne注释中添加fetch = FetchType.EAGER。
public class Book {
    @Id
    @XmlAttribute
    private String isbn;

    private String title;
    private String authors;
    private int year;

    @OneToMany(mappedBy="reservedBook",fetch = FetchType.EAGER)
    private List<Reservation> bookReservations;

    //Getters, setters, addReservation, remove Reservation
        ......................
    }

在预订类中:

 public class Reservation {

    private String username;
    private String isbn;
    @Temporal(TemporalType.DATE)
    private Date date;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "isbn")
    private Book reservedBook;

    @ManyToOne
    @JoinColumn(name = "username")
    private User userWhoReserved;

        //Getters and setters

        ...........
 }

0
解决了!但问题不在序列化上,而是EntityManager调用的find()方法无法提取预订并将其放入我的书对象中,因此列表保持为空,并且相应的元素未显示。因此,似乎应该使用Query而不是find():
Query query = entityManager.createQuery("SELECT book FROM Book book WHERE book.isbn = :_isbn ");
query.setParameter("_isbn", isbn);


//if getSingleResult() doesn't find a book, an exception will be thrown
try {
        Book book = (Book)query.getSingleResult();
        return book;
    }
    catch(RuntimeException e)
    {
        //do something
    }

此外,Book类中的@XmlAccessorType(XmlAccessType.FIELD)必须删除,并且列表的getter方法应该用@XmlElementWrapper(name = "reservations")和@XmlElement(name = "reservation")进行注释。

0

使用@XmlRootelement包装,并设置nillable="true",然后将会有一个空的<reservations>

@XmlElement
@XmlElementWrapper(nillable=true)
private List<Reservation> bookReservations;

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接