【问题标题】:Flexible marshalling with JAXB使用 JAXB 灵活编组
【发布时间】:2012-01-31 21:04:32
【问题描述】:

我希望有一种灵活的方式来编组对象。单个对象的详细版本和多个对象版本的不太详细的版本。

以我的部门模型为例:

GET /locations/1:

  <location id='1'>
    <link rel="self" href="http://example.com/locations/1"/>
    <link rel="parent" href="http://example.com/serviceareas/1"/>
    <name>location 01</name>
    <departments>
      <department id='1'>
        <link rel="self" href="http://example.com/departments/1"/>
        <name>department 01</name>
      </department>
      <department id='2'>
        <link rel="self" href="http://example.com/departments/2"/>
        <name>department 02</name>
      </department>
      <department id='3'>
        <link rel="self" href="http://example.com/departments/3"/>
        <name>department 03</name>
      </department>
    </departments>
  </location>

GET /department/1:

<department id='1'>
  <link rel="self" href="http://example.com/departments/1"/>
  <link rel="parent" href="http://example.com/locations/1"/>
  <name>department 01</name>
  <abbr>dept 01</abbr>
  ....
  <specialty>critical care</specialty>
</department>

有没有办法做到这一点?我需要有单独的实体对象吗?一个引用表进行 CRUD 操作,另一个引用列表?

【问题讨论】:

    标签: jpa-2.0 jersey eclipselink jax-rs jaxb2


    【解决方案1】:

    注意:我是EclipseLink JAXB (MOXy) 领导,也是JAXB 2 (JSR-222) 专家组的成员。

    您的问题被标记为EclipseLink,如果您使用的是EclipseLink JAXB (MOXy),您可以利用外部绑定文档将第二个映射应用到Department 类。


    上下文解析器

    JAX-RS 环境中,您可以通过 ContextResolver 来利用 MOXy 的外部绑定文档:

    import java.io.*;
    import java.util.*;     
    import javax.ws.rs.Produces;
    import javax.ws.rs.ext.*;
    import javax.xml.bind.*;
    import org.eclipse.persistence.jaxb.JAXBContextFactory;
    
    @Provider
    @Produces({"application/xml", "application/json"})
    public class DepartmentContextResolver implements ContextResolver<JAXBContext> {
    
        private JAXBContext jc;
    
        public DepartmentContextResolver() {
            try {
                Map<String, Object> props = new HashMap<String, Object>(1);
                props.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "example/bindings.xml");
                jc = JAXBContext.newInstance(new Class[] {Department.class} , props);
            } catch(JAXBException e) {
                throw new RuntimeException(e);
            } 
        }
    
        public JAXBContext getContext(Class<?> clazz) {
            if(Department.class == clazz) {
                return jc;
            }
            return null;
        }
    
    
    } 
    

    更多信息


    外部绑定文档

    默认情况下 MOXy 的外部绑定文档用于扩充带注释的模型,但如果您设置 xml-mapping-metadata-complete 标志,它将完全覆盖注释,从而允许您应用完全不同的映射:

    <xml-bindings
        xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
        package-name="example"
        xml-mapping-metadata-complete="true">
        ...
    </xml-bindings>
    

    更多信息

    更新

    此更新旨在解决您在其中一个 cmets 中提出的一些问题:

    1 .每个 ContentResolver 是否应该/可以有自己的绑定文件?

    是的,每个ContextResolver 都应该有自己的绑定文件。引入新的ContextResolver 的主要原因是为了表示二级映射。

    2 。我可以为每个 ContentResolver 提供多个(这会给我同一类的多个渲染,创建各种“视图”),也许在构造函数中指定它的位置?

    对于单个ContextResolver,您可以跨多个绑定文件表达元数据,但它们将组合成一组映射。这意味着单个ContentResolver 不能拥有单个类的多个视图。单独的ContextResolver 用于表示二级映射。

    3 .绑定文件应该放在哪里?

    我建议从类路径加载元数据文件。

    4 .我可以看到如何在资源的 GET 方法中轻松指定 ContentResolver,但是如果对象嵌入到另一个 (JPA) 对象中,该怎么做呢?在嵌入对象的 getter/setter 中?

    您的 JAX-RS 实现应该选择您的 ContextResolver,因为它带有 @Provider 注释。用于类的ContextResolver 将取决于您如何实现getContext 方法:

    public JAXBContext getContext(Class<?> clazz) {
        if(Customer.class == clazz) {
            return jc;
        }
        return null;
    }
    

    【讨论】:

    • 我引用了三个“EclipseLink(JPA 2.0)”JAR:eclipselink-2.3.0.jar、javax.persistence-2.0.jar、org.eclipse.persistence.jpa.jpql_1.0.0 。罐。 MOXy 是否包含在其中任何一个中?
    • @craig - MOXy 包含在 eclipselink-2.3.0.jar 中。这里有一篇文章解释了如何将 MOXy 配置为 JAXB 提供程序:blog.bdoughan.com/2011/05/…如果您使用的是 GlassFish,下面的文章解释了如何配置 MOXy:blog.bdoughan.com/2010/08/…
    • 我有许多与 JABX 相关的问题。您有时间在其中一间 SO 房间聊天吗?
    • @craig - 我们可以使用 Java 房间。
    • 好的,这是有道理的,但我有几个问题。 1. 每个 ContentResolver 是否应该/可以有自己的绑定文件? 2. 每个 ContentResolver 是否可以有多个(这会给我同一类的多个渲染,创建各种“视图”),也许在构造函数中指定它的位置? 3. 绑定文件应该放在哪里? 4. 我可以看到如何在资源的 GET 方法中轻松指定 ContentResolver,但是如果对象嵌入到另一个 (JPA) 对象中,该怎么做?在嵌入对象的 getter/setter 中?
    【解决方案2】:

    这里又来了一个想法。可能是个坏主意,但有点容易。

    class Department {
    
        @XmlElement(required = true)
        public Link getSelf() {
            return self;
        }
    
        @XmlElement(required = false) // default
        public Link getParent() {
            if (verbose) {
                return parent;
            }
            return null;
        }
    
        @XmlElement(required = false) // default
        public String getSpecialty() {
            if (verbose) {
                return specialty;
            }
            return null;
        }
    
        @XmlTransient
        private boolean verbose;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      • 2016-06-16
      • 1970-01-01
      相关资源
      最近更新 更多