1

というクラスがありBuildingます。

BuildingBenchAssociationレコードのリストがあります ( List<BuildingBenchAssociation> benches)

BuildingBenchAssociationIDはbuildingId、2 つのプロパティのみを持つ、呼び出さbenchId れた別のクラスによって表されます。BuildingBenchAssociationPKbuildingIdbenchId

Buildingこれは、インスタンスをマーシャリングしたときに得られる出力です

<building buildingId="9">
<benches>
DOMRecord(<?xml version="1.0" encoding="UTF-8"?><buildingBenchAssociation><benchId>245865</benchId><buildingId>9</buildingId></buildingBenchAssociation>)
</benches>
<benches>
DOMRecord(<?xml version="1.0" encoding="UTF-8"?><buildingBenchAssociation><benchId>245866</benchId><buildingId>9</buildingId></buildingBenchAssociation>)
</benches>
<benches>

DOMRecord(<?xml version="1.0" encoding="UTF-8"?>しかし、私は出力に表示されたくありません。必要な出力は次のようなものです。

<building buildingId="9">
<benches>
<buildingBenchAssociation><benchId>245865</benchId><buildingId>9</buildingId></buildingBenchAssociation>
</benches>
<benches>
<buildingBenchAssociation><benchId>245866</benchId><buildingId>9</buildingId></buildingBenchAssociation>
</benches>
<benches>

何が問題で、どうすれば修正できますか? Eclipselink MOXy ライブラリを使用しています。

参照用のクラス:

クラス1

@Entity
@Table(name="building")
@XmlRootElement
public class Building implements Serializable {
....

private List<BuildingBenchAssociation> benchs = new ArrayList<BuildingBenchAssociation>();

    @XmlIDREF
    @OneToMany(mappedBy="building")
    public List<BuildingBenchAssociation> getBenchs() {
        return benchs;
    }

    public void setBenchs(List<BuildingBenchAssociation> benchs) {
        this.benchs = benchs;
    }
}

クラス2

@Entity
@Table(name="building_bench_rel")
@XmlRootElement
public class BuildingBenchAssociation implements Serializable {
    private static final long serialVersionUID = 1L;
    private BuildingBenchAssociationPK idx;

    private Bench bench;
    private Building building;
    private byte alertFlags;
    private byte status;

    public BuildingBenchAssociation() {
            idx=new BuildingBenchAssociationPK();
    }

    @XmlID
    @XmlPath(".")
    @Id
    public BuildingBenchAssociationPK getIdx() {
        return this.idx;
    }

    public void setIdx(BuildingBenchAssociationPK id) {
        this.idx = id;
    }

    @Column(name="ALERT_FLAGS")
    public byte getAlertFlags() {
        return this.alertFlags;
    }

    public void setAlertFlags(byte alertFlags) {
        this.alertFlags = alertFlags;
    }

    @Column(name="STATUS", insertable=false, updatable=false)
    public byte getStatus() {
        return this.status;
    }

    public void setStatus(byte status) {
        this.status = status;
    }

    @XmlIDREF
    @ManyToOne
    @JoinColumn(name="BENCH_ID",insertable=false,updatable=false)
    public Bench getBench() {
        return bench;
    }


    public void setBench(Bench bench) {
        this.bench = bench;
        this.idx.setBenchId(bench==null?null:bench.getBenchId());
    }

    @XmlIDREF
    @ManyToOne
    @JoinColumn(name="BUILDING_ID",insertable=false,updatable=false)
    public Building getBuilding() {
        return building;
    }

    public void setBuilding(Building building) {
        this.building = building;
        this.idx.setBuildingId(building==null?null:building.getBuildingId());
    }

}

クラス3

@Embeddable
@XmlRootElement
public class BuildingBenchAssociationPK implements Serializable {
...

    private Integer buildingId;
    private Integer benchId;

    public BuildingBenchAssociationPK() {
    }

    @XmlKey
    @Column(name="BUILDING_ID")
    public Integer getBuildingId() {
        return this.buildingId;
    }
    public void setBuildingId(Integer buildingId) {
        this.buildingId = buildingId;
    }

    @XmlKey
    @Column(name="BENCH_ID")
    public Integer getBenchId() {
        return this.benchId;
    }
    public void setBenchId(Integer benchId) {
        this.benchId = benchId;
    }
}
4

1 に答える 1

2

以下は、現在 MOXy を使用してこのユース ケースをマッピングする方法です。このユースケースをマッピングしやすくするために、次の拡張リクエストを開きました。


参照オブジェクト

埋め込み ID (EmployeeId)

以下は、埋め込み ID クラスの例です。

import java.math.BigDecimal;
import javax.persistence.*;
import javax.xml.bind.annotation.*;

@Embeddable
@XmlAccessorType(XmlAccessType.FIELD)
public class EmployeeId {

    @Column(name="E_ID")
    BigDecimal eId;

    String country;

}

埋め込み ID を持つクラス (従業員)

埋め込み ID クラスを XML 関係のキーとして使用したいと考えています。現在、MOXy では注釈を使用してこれを行うことは許可されていないため、@XmlCustomizer注釈を利用してプログラムでメタデータを変更します。

import java.util.List;
import javax.persistence.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;

@Entity
@IdClass(EmployeeId.class)
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlCustomizer(EmployeeCustomizer.class)
public class Employee {

    @EmbeddedId
    @XmlPath(".")
    EmployeeId id;

    @OneToMany(mappedBy="contact")
    List<PhoneNumber> contactNumber;

}

従業員のマッピング メタデータのカスタマイズ (EmployeeCustomizer)

カスタマイザー クラスでは、埋め込みクラスのキーを構成するマッピングの XPath を指定します。

import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;

public class EmployeeCustomizer implements DescriptorCustomizer {

    @Override
    public void customize(ClassDescriptor descriptor) throws Exception {
        descriptor.addPrimaryKeyFieldName("eId/text()");
        descriptor.addPrimaryKeyFieldName("country/text()");
    }

}

参照オブジェクト

電話番号

また、複合キーに基づいてマッピングをプログラムで追加する必要があるため、ここでも@XmlCustomizerアノテーションを使用します。

import javax.persistence.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;

@Entity
@XmlAccessorType(XmlAccessType.FIELD)
@XmlCustomizer(PhoneNumberCustomizer.class)
public class PhoneNumber {

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="E_ID", referencedColumnName = "E_ID"),
        @JoinColumn(name="E_COUNTRY", referencedColumnName = "COUNTRY")
    })
    Employee contact;

}

PhoneNumber のマッピング メタデータのカスタマイズ (PhoneNumberCustomizer)

このカスタマイザでは、デフォルトのマッピングを削除し、複合キーに基づいてプログラムで新しいマッピングを作成します。

import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMapping;

public class PhoneNumberCustomizer  implements DescriptorCustomizer {

    @Override
    public void customize(ClassDescriptor descriptor) throws Exception {
        descriptor.removeMappingForAttributeName("contact");

        XMLObjectReferenceMapping contactMapping = new XMLObjectReferenceMapping();
        contactMapping.setAttributeName("contact");
        contactMapping.setReferenceClass(Employee.class);
        contactMapping.addSourceToTargetKeyFieldAssociation("contact/@eID", "eId/text()");
        contactMapping.addSourceToTargetKeyFieldAssociation("contact/@country", "country/text()");
        descriptor.addMapping(contactMapping);
    }

}

デモコード

次のデモ コードを使用して、すべてが機能することを実証できます。

デモ

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Employee.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("input.xml");
        Employee employee = (Employee) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(employee, System.out);
    }

}

input.xml/出力

<?xml version="1.0" encoding="UTF-8"?>
<employee>
   <eId>10</eId>
   <country>Canada</country>
   <contactNumber>
      <contact eID="10" country="Canada"/>
   </contactNumber>
   <contactNumber>
      <contact eID="10" country="Canada"/>
   </contactNumber>
</employee>

詳細については

于 2013-05-07T18:41:31.070 に答える