【问题标题】:How to write Data into XML file using JAXB?如何使用 JAXB 将数据写入 XML 文件?
【发布时间】:2014-03-12 04:14:50
【问题描述】:

我正在使用 eclipse-link,我正在从表中检索数据并尝试使用 JAXB 将检索到的数据存储到 XML 文件中。写入 XML 文件时,最后一条记录仅保存在该文件中。

这里用户是我的 POJO 类有两个字段

@XmlRootElement
public class User implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

private  String name;

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

public void setId(int id) {
    this.id = id;
}
@XmlElement
public String getName() {
    return name;
}

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

 public User()
{

}
}

下面是我的代码:

public class ObjectToXml {
private static int startingIndex = 0;
private static int maxIndex= 10;

public static void main(String[] args) {

    EntityManager entityManager = EntityManagerUtil.getEmf()
            .createEntityManager();
    Query query = entityManager.createQuery("Select u from User u");

    System.out.println("Total Number of Records"
            + query.getResultList().size());
    try {

        JAXBContext contextObj = JAXBContext.newInstance(User.class);

        Marshaller marshallerObj = contextObj.createMarshaller();
        marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);          

        query.setFirstResult(startingIndex );
        query.setMaxResults(maxIndex);
        List<User> user = query.getResultList();

        Iterator iterator = user.iterator();
        while (iterator.hasNext()) {
            User student = (User) iterator.next();  
        MarshallerObj.marshal(student, new FileOutputStream("User.xml"));

        }

    } catch (Exception e) {
        e.printStackTrace();
    }

    finally {
        entityManager.close();

    }
}
}

这里我得到 10 条记录。但是在存储最后一条记录时只保存在 XML 中

我的结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<user id="10">
<name>prabha</name> 
</user> 

【问题讨论】:

    标签: java xml jpa jaxb eclipselink


    【解决方案1】:

    你需要使用@XmlElements注解。

    Marshaller.marshal() 只是将对象转换为字节流并写入输出流。因此它将覆盖输出流中的现有数据。在您的情况下,由于 marshallerObj.marshal(student, new FileOutputStream("User.xml")); 在循环内,因此最终文件将始终包含列表中的最后一个对象。即在第一次迭代中,它将第一个对象写入文件,在第二次迭代中,它将用第二个对象覆盖文件,在第三次迭代中,它将用第三个对象覆盖文件,依此类推。

    要编组对象列表,解决方案之一是创建一个容器对象,该对象将维护所有用户/学生的列表,然后编组容器对象。

    类似问题请参考link

    在您的情况下,容器类应如下所示:

    @XmlRootElement(name = "Users")
    public class Users
    {
        private List<User> users = new ArrayList<User>();
    
        @XmlElements(value = {@XmlElement(name = "User", type = User.class)})
        @XmlElementWrapper
        public List<User> getUsers() {
            return users;
        }
    
        public void addUser(User user) {
            users.add(user);
        }
    }
    

    以及编组用户的代码:

    Users users = new Users();
    
    List<User> usersList = query.getResultList();
    
    for(User user : usersList) {
        users.addUser(user);
    }
    
    marshallerObj.marshal(users, new FileOutputStream("User.xml"));
    

    【讨论】:

    • 您还需要使用JAXBContext contextObj = JAXBContext.newInstance(User.class, Users.class);将用户类添加到上下文中
    • 谢谢@Sanket Meghani,在 user3156284 的帮助下我得到了 o/p。
    【解决方案2】:

    由于您正在为每个 User 对象创建 xml 文件,因此当程序从 DB 获取新用户时,这些对象将继续替换
    因此,创建一个 POJO 类 Users,其中 List of User 作为属性,

    public class Users 
    {
    //Users grouping
    private List<User> user;
    
    public void setUser(List<ProductInfo> userInfo) 
    {
        this.user = userInfo;
    }
    
    @XmlElement(name="user")
    public List<User> getUser() {
        return user;
    }
    

    }

    然后在代码部分为 Users 类创建 JAXBContext 的实例,如下所述

     JAXBContext contextObj = JAXBContext.newInstance(Users.class);
    

    现在修改 while 循环以将所有用户信息设置到 Users 对象中,并且 marshar Users 对象而不是编组 User 对象。

    Users users = new Users();
    while (iterator.hasNext()) {
          User student = (User) iterator.next();  
          users.setUser(student);
    }
    MarshallerObj.marshal(users, new FileOutputStream("User.xml"));
    

    【讨论】:

    • 我现在编辑了你的代码,我只在你的代码的帮助下得到了 o/p。非常感谢@user3156284
    • 如果对您有帮助,请将答案标记为正确。 :)
    【解决方案3】:

    因为MarshallerObj.marshal(student, new FileOutputStream("User.xml")); 每次都会创建新的文件 o/p 流并清除 prev 内容。从您的 while 循环中创建此 o/p 流实例。这应该会有所帮助。

    【讨论】:

    • 谢谢,我把那个放在while循环外面,但结果是一样的。我也为循环外的用户创建了新对象
    • 尝试写入 System.out 而不是文件输出流,看看它打印什么
    • 它正在打印 10 个对象。
    • 发布您的具有文件 o/p 流和 while 循环的代码块
    • com.company.User@45389b3f com.company.User@758689a com.company.User@3d3b5a3a com.company.User@3a0b53e com.company.User@2bdafb4e com.company.User@535c97e4 com.company.User@63f8247d com.company.User@3823bdd1 com.company.User@32830122 com.company.User@36bf7916
    【解决方案4】:

    也许您应该保留一个 FileOutputStream 并不断编入其中,而不是在每次迭代时创建一个新的。

    【讨论】:

    • 谢谢,那我该做什么了
    • FileOutputStream fos = new FileOutputStream("User.xml"); while (iterator.hasNext()) { 用户学生 = (User) iterator.next(); MarshallerObj.marshal(学生,fos); }
    • XML 文档中只允许有一个顶级元素。错误处理资源...当我打开 XML 时,它显示如下
    • 尝试编组整个user 列表而不是每个用户。
    • 你的意思是在 while 循环之外我必须做编组 na
    猜你喜欢
    • 2010-12-27
    • 2014-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 2014-06-16
    • 2011-09-06
    相关资源
    最近更新 更多