Serialize a JAXB object via its ID?

前端 未结 2 1149
谎友^
谎友^ 2020-12-06 14:20

In my data model, I have something to this effect:

@Entity
public class Target {

    @Id 
    @GeneratedValue
    private Long id;

    /* ...etc... */
}

@         


        
相关标签:
2条回答
  • 2020-12-06 15:01

    You could use an XmlAdapter for this use case:

    package forum7278406;
    
    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class TargetAdapter extends XmlAdapter<Long, Target> {
    
        @Override
        public Long marshal(Target target) throws Exception {
            return target.getId();
        }
    
        @Override
        public Target unmarshal(Long id) throws Exception {
            Target target = new Target();
            target.setId(id);
            return target;
        }
    
    }
    

    The XmlAdapter is registered on the Dependency class using the @XmlJavaTypeAdapter annotation:

    package forum7278406;
    
    import javax.persistence.*;
    import javax.xml.bind.annotation.*;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    @Entity
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Dependency {
    
        @Id
        @GeneratedValue
        private Long id;
    
        @ManyToOne(optional=false)
        @Column(name="target_id")
        @XmlJavaTypeAdapter(TargetAdapter.class)
        private Target target;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public Target getTarget() {
            return target;
        }
    
        public void setTarget(Target target) {
            this.target = target;
        }
    
    }
    

    Going Further

    Instead of just creating a new instance of Target we could use an EntityManager to query the corresponding instance from the database. Our XmlAdapter would be changed to look something like:

    package forum7278406;
    
    import javax.persistence.EntityManager;
    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class TargetAdapter extends XmlAdapter<Long, Target> {
    
        EntityManager entityManager;
    
        public TargetAdapter() {
        }
    
        public TargetAdapter(EntityManager entityManager) {
            this.entityManager = entityManager;
        }
    
        @Override
        public Long marshal(Target target) throws Exception {
            return target.getId();
        }
    
        @Override
        public Target unmarshal(Long id) throws Exception {
            Target target = null;
            if(null != entityManager) {
                target = entityManager.find(Target.class, id);
            }
            if(null == target) {
                target = new Target();
                target.setId(id);
            }
            return target;
        }
    
    }
    

    Now to set the instance of EntityManager on our XmlAdapter, we can do the following:

    Unmarshaller umarshaller = jaxbContext.createUnmarshaller();
    TargetAdapter targetAdatper = new TargetAdapter(entityManager);
    unmarshaller.setAdapter(targetAdapter);
    
    0 讨论(0)
  • 2020-12-06 15:03

    It works for EclipseLink MOXy with XmlID and XmlIDRef (but fails for sun JAXB, where XmlID must be string)

    @Entity
    @XmlRootElement
    public class Target {
        @Id
        @GeneratedValue
        @XmlID
        @XmlElement
        private Long id;
    }
    
    
    @Entity
    @XmlRootElement
    public class Dependency {
    
        @Id
        @GeneratedValue
        @XmlElement
        private  Long id;
    
        @ManyToOne(optional = false)
        @Column(name = "target_id")
        @XmlIDREF
        @XmlElement(name = "targetId")
        private Target target;
    }
    
    0 讨论(0)
提交回复
热议问题