gpt4 book ai didi

hibernate - (moxy) jaxb 编码(marshal)处理和 hibernate 代理对象

转载 作者:行者123 更新时间:2023-12-04 15:03:31 26 4
gpt4 key购买 nike

在过去的几天里,我尝试使用 MOXy JAXB 来支持 Hibernate 模型的 XML 编码/解码。尝试这样做时,我遇到了 hibernate 代理对象的问题。
考虑这样的事情:

public class User {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "address")
public Address getAddress() {
return address;
}
}

public abstract class Address {
// Something
}

public class CoolAddress extends Address {
public String getSomething() {
return something;
}
}

我尝试通过以下方式使用 MOXy JAXB 映射此代码:
@XmlAccessorType(XmlAccessType.NONE)
public class User {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "address")
@XmlElement
public Address getAddress() {
return address;
}
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlSeeAlso(CoolAddress.class)
public abstract class Address {
// Something
}

@XmlAccessorType(XmlAccessType.NONE)
public class CoolAddress extends Address {
@XmlElement
public String getSomething() {
return something;
}
}

我的问题是 hibernate 实例化了通过对用户调用 getAddress() 获得的地址的代理对象。然后,当 JAXB 尝试编码(marshal)对象时,它无法发现它实际上是它试图编码(marshal)的 CoolAddress,这导致 CoolAddress 中的属性未被编码(marshal)。

我已经用谷歌搜索/考虑了以下可能的解决方案:
  • 以某种方式从 JAXB 获得回调,允许我用另一个对象替换正在编码的对象。这将允许我从代理获取真实对象。
  • 触摸模型中的所有对象,这将使 hibernate 获取真实的对象。除了手动运行所有非 transient 属性之外,我找不到任何聪明的方法来执行此操作,这很乏味。
  • 将 hibernate 设置为在我正在编码模型的 session 中使用预先获取。

  • 我正在寻找替代建议,或者上述建议之一是否可能(且易于)实现。任何帮助表示赞赏:)。

    最佳答案

    要解决此 hibernate 问题,您可以使用 XmlAdapter . XmlAdapter 看起来类似于 marshal 方法中的逻辑是从代理转换为真实对象:

    package forum6838323;

    import javax.xml.bind.annotation.adapters.XmlAdapter;

    public class AddressAdapter extends XmlAdapter<Address, Address> {

    @Override
    public Address unmarshal(Address v) throws Exception {
    return v;
    }

    @Override
    public Address marshal(Address v) throws Exception {
    // TODO Auto-generated method stub
    return null;
    }

    }

    您配置了 XmlAdapter如下:
    public class User {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "address")
    @XmlJavaTypeAdapter(AddressAdapter.class)
    public Address getAddress() {
    return address;
    }
    }

    如果您需要将初始化的 XmlAdapter 传递给 JAXB 编码器,您也可以这样做,请参阅以下示例:
  • Using JAXB to cross reference XmlIDs from two XML files


  • 使用 EclipseLink JPA 的替代方法

    注意:EclipseLink JPA 中的延迟加载不会导致此问题:

    用户
    package forum6838323;

    import javax.persistence.*;
    import javax.xml.bind.annotation.XmlAttribute;
    import javax.xml.bind.annotation.XmlRootElement;

    @Entity
    @Table(name="users")
    @XmlRootElement
    public class User {

    private int id;
    Address address;

    @Id
    @XmlAttribute
    public int getId() {
    return id;
    }

    public void setId(int id) {
    this.id = id;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "address")
    public Address getAddress() {
    return address;
    }

    public void setAddress(Address address) {
    this.address = address;
    }

    }

    地址
    package forum6838323;

    import javax.persistence.*;
    import javax.xml.bind.annotation.XmlAttribute;
    import javax.xml.bind.annotation.XmlSeeAlso;

    @Entity
    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name="TYPE", discriminatorType=DiscriminatorType.STRING)
    @DiscriminatorValue("ADDRESS")
    @XmlSeeAlso(CoolAddress.class)
    public class Address {

    private int id;
    private String street;

    @Id
    @XmlAttribute
    public int getId() {
    return id;
    }

    public void setId(int id) {
    this.id = id;
    }

    public String getStreet() {
    return street;
    }

    public void setStreet(String street) {
    this.street = street;
    }

    }

    CoolAddress
    package forum6838323;

    import javax.persistence.*;

    @Entity
    @DiscriminatorValue("COOL")
    public class CoolAddress extends Address {

    private String something;

    public String getSomething() {
    return something;
    }

    public void setSomething(String something) {
    this.something = something;
    }

    }

    演示
    package forum6838323;

    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;

    public class Demo {

    public static void main(String[] args) throws Exception {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("Forum6838323");
    EntityManager em = emf.createEntityManager();

    User user = em.find(User.class, 2);
    System.out.println("user.address BEFORE marshal: " + user.address);

    JAXBContext jc = JAXBContext.newInstance(User.class);
    Marshaller marshaller = jc.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(user, System.out);

    System.out.println("user.address AFTER marshal: " + user.address);
    }

    }

    输出

    您可以从输出中看到地址值被延迟加载,因为该字段在 marshal 之前为 null 并在之后填充:
    user.address BEFORE marshal:  null
    [EL Finest]: 2011-07-27 11:47:13.118--ServerSession(23503403)--Thread(Thread[main,5,main])--Execute query ReadObjectQuery(name="Forum6838323" referenceClass=Address )
    [EL Finest]: 2011-07-27 11:47:13.118--ServerSession(23503403)--Connection(10272075)--Thread(Thread[main,5,main])--Connection acquired from connection pool [default].
    [EL Fine]: 2011-07-27 11:47:13.118--ServerSession(23503403)--Connection(10272075)--Thread(Thread[main,5,main])--SELECT ID, TYPE, STREET, SOMETHING FROM ADDRESS WHERE (ID = ?)
    bind => [2]
    [EL Finest]: 2011-07-27 11:47:13.118--ServerSession(23503403)--Connection(10272075)--Thread(Thread[main,5,main])--Connection released to connection pool [default].
    [EL Finest]: 2011-07-27 11:47:13.118--UnitOfWork(6131844)--Thread(Thread[main,5,main])--Register the existing object forum6838323.CoolAddress@109ea96
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <user id="2">
    <address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="coolAddress" id="2">
    <street>2 B Road</street>
    <something>Cool Road</something>
    </address>
    </user>
    user.address AFTER marshal: forum6838323.CoolAddress@83b1b

    关于hibernate - (moxy) jaxb 编码(marshal)处理和 hibernate 代理对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6838323/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com