Сериализация объекта JAXB через его идентификатор? - PullRequest
4 голосов
/ 02 сентября 2011

В моей модели данных есть что-то на этот счет:

@Entity
public class Target {

    @Id 
    @GeneratedValue
    private Long id;

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

@Entity
public class Dependency {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(optional=false)
    @Column(name="target_id")
    private Target target;

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

Я уже сериализую Target просто отлично, но мне нужно сериализовать Dependency. По сути, мне нужно что-то вроде этого:

<dependency>
    <id>100</id>
    <targetId>200</targetId>
</dependency>

Есть ли способ сделать это в аннотациях JAXB без изменения моей модели?

Ответы [ 2 ]

7 голосов
/ 02 сентября 2011

Вы можете использовать XmlAdapter для этого варианта использования:

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;
    }

}

XmlAdapter зарегистрирован в классе Dependency с использованием аннотации @XmlJavaTypeAdapter:

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;
    }

}

Идем дальше

Вместо простого создания нового экземпляра Target мы можем использовать EntityManager для запроса соответствующего экземпляра из базы данных.Наш XmlAdapter будет изменен, чтобы выглядеть примерно так:

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;
    }

}

Теперь, чтобы установить экземпляр EntityManager на нашем XmlAdapter, мы можем сделать следующее:

Unmarshaller umarshaller = jaxbContext.createUnmarshaller();
TargetAdapter targetAdatper = new TargetAdapter(entityManager);
unmarshaller.setAdapter(targetAdapter);
2 голосов
/ 02 сентября 2011

Работает для EclipseLink MOXy с XmlID и XmlIDRef (но не работает для Sun JAXB, где XmlID должен быть строкой)

@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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...