【问题标题】:Unable to store data in database after unmarshalling a xml resource解组 xml 资源后无法将数据存储在数据库中
【发布时间】:2015-06-27 01:27:01
【问题描述】:

我有两个实体ValCursValute,我正在映射一个远程xml 资源。数据仅针对Valute实体存储在数据库中。

这是我的实体:

ValCurs实体:

@Entity
@Table(name = "valCurs")
@XmlRootElement(name="ValCurs")
@XmlAccessorType(XmlAccessType.FIELD)
public class ValCurs {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;

@XmlAttribute(name = "Date")
private String date;

@XmlElement(name = "Valute")
private ArrayList<Valute> allValutes;


public Long getId() {
    return id;
}

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

public ArrayList<Valute> getAllValutes() {
    return allValutes;
}

public void setAllValutes(ArrayList<Valute> allValutes) {
    this.allValutes = allValutes;
}

public String getDate() {
    return date;
}

public void setDate(String date) {
    this.date = date;
}

}

Valute实体

@Entity
@Table(name = "valute")
@XmlAccessorType(XmlAccessType.FIELD)
public class Valute {

@Id
@Column
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "char_code")
@XmlElement(name = "CharCode")
private String charCode;

@Column(name = "nominal")
@XmlElement(name = "Nominal")
private Integer nominal;

@Column(name = "value")
@XmlElement(name = "Value")
private Float value;

@Column(name = "name")
@XmlElement(name = "Name")
private String name;

public Long getId() {
    return id;
}

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

public String getCharCode() {
    return charCode;
}

public void setCharCode(String charCode) {
    this.charCode = charCode;
}

public Integer getNominal() {
    return nominal;
}

public void setNominal(Integer nominal) {
    this.nominal = nominal;
}

public Float getValue() {
    return value;
}

public void setValue(Float value) {
    this.value = value;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

}

我是这样解组的:

        URL url = new URL(BNM);
        InputSource is = new InputSource(url.openStream());

        // Converting a XML to java object with JAXB, (UnMarshalling).
        JAXBContext jaxbContext = JAXBContext.newInstance(ValCurs.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        ValCurs valCurs = (ValCurs) jaxbUnmarshaller.unmarshal(is);

        // Extracting the list of Valutes from the root xml
        ArrayList<Valute> listOfValutes = valCurs.getAllValutes();

        // Storing data into database
        for (Valute valute : listOfValutes) {
            valuteService.add(valute);
        }

        valCursService.add(valCurs);

当我运行代码时,它会抛出一个:could not serialize; nested exception 我可以理解为什么(它不能在表格的一个单元格中序列化:private ArrayList&lt;Valute&gt; allValutes;)。

我需要从ValCurs 获取iddate,但我无法实现(valCursService.add(valCurs); 抛出异常,因此我无法将数据存储在数据库中。)

我的问题是这样的:我如何将来自ValCurs 的数据存储在一个表中,(也许我在 Jaxb 注释技术中遗漏了一些东西,我在 java 的持久性方面真的很新)。

P.S. 我正在解析的 Xml 是这样的:

<ValCurs Date="20.04.2015" name="Official exchange rate">
<Valute ID="47">
<NumCode>978</NumCode>
<CharCode>EUR</CharCode>
<Nominal>1</Nominal>
<Name>Euro</Name>
<Value>19.3441</Value>
</Valute>
<Valute ID="44">
<NumCode>840</NumCode>
<CharCode>USD</CharCode>
<Nominal>1</Nominal>
<Name>US Dollar</Name>
<Value>18.0558</Value>
</Valute>
</ValCurs>

【问题讨论】:

    标签: java xml hibernate spring-mvc jaxb


    【解决方案1】:

    所以你在 ValCurls 和 value 之间有 oneToMany 关系,你需要通知 JPA 来存储这个关系。

    缺少的位是集合上的@OneToMany 注解:

    @Entity
    @Table(name = "valCurs")
    @XmlRootElement(name="ValCurs")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class ValCurs {    
    ...    
       @XmlElement(name = "Valute")
       @OneToMany(cascade=CascadeType.ALL,orphanRemoval = true)
       private List<Valute> allValutes; //you should use List rather than ArrayList
    

    cascade=CascadeType.ALL 大致意味着如果您插入新的 ValCurs,那么它的 Valutes 也会被插入,如果您删除 ValCurs,那么相应的 Valutes 也会被删除。 orphanRemoval = true 的效果是,如果您从 allValutes 列表中删除一个 Valuete,它也会从表中删除。

    现在,要在 DB 中表示关系,必须在 ValCurs 和它的 Valute 之间建立链接。最简单的方法是在 Valute 表中包含 ValCurs 的 id 的“父”列。您可以通过添加 joincolumn 注释来实现:

       @XmlElement(name = "Valute")
       @OneToMany(cascade=CascadeType.ALL,orphanRemoval = true)
       @JoinColumn(name ="VALCURS_ID")
       private List<Valute> allValutes; //you should use List rather than 
    

    你也可以有一个连接表(谷歌怎么做)。

    我不知道您的 valCursService 实现,但是通过级联设置,您只需要保留 ValCurs,相关的值将自动保存。

    所以在 JPA 中:

    EntityManager em = ...;
    em.persist(valCurs); //no need for valuteService.add(valute);
    

    处于休眠状态:

    Session session = ...;
    session.save(valCurs);
    

    【讨论】:

    • 感谢您的回复,但无论如何,现在 tomcat 告诉我:严重:错误 listenerStart。更改为@OneToMany 后,我无法读取 XML。我的服务是在db中存储数据的简单服务:public void add(ValCurs valCurs) { valCursDao.save(valCurs); } where ValCursDao extends JpaRepository&lt;ValCurs, Long&gt;{}
    • 贴出整个错误,不能是xml相关,而是数据库映射错误。
    • SEVERE: Context [] startup failed due to previous errors Apr 20, 2015 5:08:11 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc SEVERE: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered. [2015-04-20 05:08:11,654] Artifact exchange-rate-app-api:war exploded: Error during artifact deployment. See server log for details.
    • 我早些时候在提出List 时收到了这个错误,但是当我更改为ArrayList 时,它很高兴地编译了......(这对我来说很奇怪)。这就是我使用ArrayList的原因。
    • 实际错误是否在日志中较早或不在此日志文件中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 1970-01-01
    相关资源
    最近更新 更多