当前位置: 首页 > 面试题库 >

(moxy)jaxb封送处理和休眠代理对象

孟茂
2023-03-14
问题内容

在过去的几天中,我尝试使用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实例化了通过在User上调用getAddress()获得的地址的代理对象。然后,当JAXB尝试封送对象时,它无法发现它实际上是它要封送的CoolAddress,这导致CoolAddress中的属性未被封送。

我已经搜寻/考虑了以下可能的解决方案:

  • 以某种方式从JAXB获得回调,允许我用另一个替换被封送的对象。这将允许我从代理获取真实对象。
  • 触摸模型中的所有对象,这将使hibernate模式获取实际对象。除了手动运行所有非瞬态属性之外,我还没有找到任何明智的方法来完成此操作,这非常安静。
  • 将hibernate设置为在我正在整理模型的会话中使用渴望获取。

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


问题答案:

要解决此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;
    }
}

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

}

酷地址

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

}

输出量

您可以从输出中看到地址值被延迟加载,因为该字段在编组之前为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 / JPA与数据库进行事务。 我不是DBA,客户端使用了我的应用程序,即RESTful Web服务。我的问题是数据库已更改(不是很频繁,但仍在更改)。另外,客户端并不总是尊重我的应用程序的输入(长度,类型等)。发生这种情况时,Hibernate会引发异常。异常很难翻译和从日志中读取,因为它具有嵌套的异常并且由很多文本组成:就像我说

  • 问题内容: 目前,我在 每个 Controller方法中 都 重复了以下代码: 这是正确的方法还是有更好的方法,也许在一个我可以引用的单独的类中?如果是这样,怎么办?每当我尝试将其放在单独的类中并从其他类中引用它时,它都会失败。 编辑 :我正在尝试使用尽可能少的外部库。如果Java在JDK中内置了ORM / JPA实现,我就不会使用Hibernate。 问题答案: 我本人已经遇到了很多次。通常,我

  • 我有一个关于通过JAXB封送的小问题。 当前我有一个对象的HashMap 由自定义HashMapAdapter封送的being 封送基于以下文章:http://blog.bdoughan.com/2013/06/moxys-xmlvariableNode-using-maps-key-as.html HashMap由布尔值、长值或字符串值填充。 因此,关于Blog,预期的JSON输出应该是: 西蒙

  • 问题内容: 如何取消代理hibernate对象,以支持多态? 考虑以下示例。A和B类是两个hibernate实体。B具有两个子类型C和D。 该代码无法执行C或D块,因为B集合已被延迟加载,并且B的所有实例均为Hibernate代理。我想要一种取消代理的方法。 注意:我意识到可以优化查询以急切地获取所有B。我正在寻找替代方案。 问题答案: 这是我们的解决方案,已添加到持久性工具中:

  • 问题内容: 我有一个dao,它基本上使用hibernate将记录插入到一​​个表中,该dao用标记为注释,并且我有一个服务,该服务会生成其他一些东西,然后调用我的dao。我的服务也标注了使用。 我叫服务循环。我在dao上的插入内容是否可以批量或一个接一个地工作?我如何确定它们可以批量工作?hibernateTransaction Manager是否管理批处理插入? 我正在使用Oracle DB。