【问题标题】:Unmarshall an XML file and save to database in Java解组 XML 文件并用 Java 保存到数据库
【发布时间】:2020-12-15 11:53:59
【问题描述】:

我有以下 XML 文件以 Java 上传到 unmarshall:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MyValues>
    <Type Value="ABC">
        <CustomerName>Sample</CustomerName>
        <EmailAddress>sample@abcd.com</EmailAddress>
        <PhoneNumber>1234567890</PhoneNumber>
        <HardwareKey>abc-def-123-456</HardwareKey>
    </Type>
</MyValues>

我想将此文件的值上传到我的 Spring 应用程序中的数据库。要解组的 Java 代码是:

String transformedFileName = TRANSFORMED_FILE_DIRECTORY+"/"+fileName;

JAXBContext context = JAXBContext.newInstance(CustomerDetails.class);
        Unmarshaller um = context.createUnmarshaller();

        customerDetails = (CustomerDetails) um.unmarshal(new InputStreamReader(
                new FileInputStream(transformedFileName), StandardCharsets.UTF_8));
        
        System.out.println(customerDetails);

CustomerDetails.java 是:


@Entity
@Table(name="customerDetails")
@EntityListeners(AuditingEntityListener.class)
public class CustomerDetails {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    private String type;
    
    private String hardwareKey;
    
    private String emailAddress;
    
    private Long phoneNumber;
    
    private String customerName;

    public Long getId() {
        return id;
    }

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

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getHardwareKey() {
        return hardwareKey;
    }

    public void setHardwareKey(String hardwareKey) {
        this.hardwareKey = hardwareKey;
    }

    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    public Long getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(Long phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }
}

这是我在运行时遇到的错误:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"MyValues"). Expected elements are (none)

我无法更改文件值和结构,必须将文件值保存在数据库中。如何克服此错误以及如何保存值?我做错了什么?

【问题讨论】:

    标签: java spring xml-parsing jaxb unmarshalling


    【解决方案1】:

    我猜想将同一个类同时用于 ORM 和 JAXB 是不可能的。

    我建议使用 JDOM 或类似库读取 XML 文件,然后手动将 xml 元素映射到 CustomerDetail 对象。像这样的:

    import java.io.File;
    import org.jdom2.Document;
    import org.jdom2.Element;
    import org.jdom2.input.SAXBuilder;
    
    public class XmlParsing {
      public static void main(String[] args) throws Exception {
        Document document = new SAXBuilder().build(new File("test.xml"));
        for(Element typeElement : document.getRootElement().getChildren("Type")) {
          CustomerDetails customerDetails = new CustomerDetails();
          customerDetails.setType(typeElement.getAttributeValue("Value"));
          customerDetails.setCustomerName(typeElement.getChildText("CustomerName"));
          // etc.
          // save customerDetails to database
        }
      }
    }
    

    【讨论】:

    • 这正在工作..如果我执行 customerDetails.getCustomerName(),我得到空指针异常,即使在设置客户名称时。
    • 似乎与这里提出的问题无关。提出一个新问题,并提供更多信息。
    • 错误是:java.lang.NullPointerException: null at com.licensegeneration.licenseGenerator.service.FileService.storeFile(FileService.java:62) ~[classes/:na] 第62行是: customerDetails.setCustomerName(typeElement.getChildText("CustomerName"));进口是:import org.jdom2.Document;导入 org.jdom2.Element;导入 org.jdom2.input.SAXBuilder;
    【解决方案2】:

    假设到目前为止一切正常并且 xml 格式固定(并且 xml 大小很小)。

    (将 注释混合使用很可能/方便/方便,但是xml 和数据库的结构应该匹配。)

    在这种情况下(结构差异太复杂/xml调整不是一个选项,)我们应该:

    1. 从(固定的,很少更新的)xml/xsd 生成 jaxb 类(es MyValues)。 (“手动”,或使用一些工具:https://www.google.com/search?q=jaxb+generate+classes+from+xmlhttps://docs.oracle.com/cd/B19306_01/appdev.102/b14252/adx_j_jaxb.htmhttps://www.baeldung.com/jaxb)...直到unmarshall(),产生理想的结果(测试!)。

    2. 将这个/ese 类检查到源代码管理中,并且仅/每当 XML 更改时维护。

    3. 使用这个生成的类,来(查找和更新现有的或者?)创建newCustomerDetails...比如:

       JAXBContext context = JAXBContext.newInstance(MyValues.class);
       Unmarshaller um = context.createUnmarshaller();
      
       MyValues myValues = (MyValues) um.unmarshal(new InputStreamReader(
               new FileInputStream(transformedFileName), StandardCharsets.UTF_8));
      
       // get a new db id:
       CustomerDetails customerDetails = new CustomerDetails(); 
      
       // ... or search for existing... !? (myValues.getEmail()!?;)
      
       // if you want to learn about "object mappers", just do it, otherwise, you have to "manually"...:
       customerDetails.setXXX(myValues.getXXX()); // ...
      
      // and finally do something with customerDetails... 
      // like: repository.save(custpomerDetails);  
      // and: LOGGER.debug("customer saved: {}", customerDetails.getId());
      

    但是,xml 元素名称MyValues 建议,该 xml 正在“建设中”,所以也请尝试将其调整为“所需”:

     <?xml version="1.0" encoding="UTF-8"?>
     <!-- name space ?? -->
     <CutomerDetails>
        <type>some type</type>
        <hardwareKey>someHardwareKey</hardwareKey>
        <emailAddress>john.doe@sample.com</emailAddress>
        <phoneNumber>+12345678901</phoneNumber>
        <customerName>John Doe</customerName>
    </CustomerDetails>
    

    ...然后添加@XmlRootElement(在CustomerDetails 类之上)并通过添加@XmlTransient(到public void setId() ...)“忽略id”,可以您的原始代码工作正常。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2012-11-06
    相关资源
    最近更新 更多