使用XStream解析复杂XML并插入数据库

Posted psyche61

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用XStream解析复杂XML并插入数据库相关的知识,希望对你有一定的参考价值。

标注黄色地方:我需要加深学习!!!

我写的是webservice,目前具体写webservice的步骤我还不清楚, 整理完小知识开始整理webservice!

针对以下格式的XML进行解析

<?xml version=”1.0” encoding=”UTF-8”?>

<Data>

  <Bean>

    <A>a</A>

    <B>b</B>

    <C>1</C>

 

    <A>a</A>

    <B>b</B>

    <C>2</C>

  </Bean>

    <D>

      <E></E>  

    </D>

</Data>

 项目中:我们一次性解析10条Bean,这里,举例两条,Data中包含十个Bean。

我们需要将A、B、C的数据存入数据库,这里,老大说采用一对多的方式进行存储。项目中我们使用hibernate自动生成表。举例中我还是按照项目的写法走,当然自己建表并建立两表间的关系会更容易。建立一对多关系。

(1)、导入依赖,我是oracle,mysql来回切换用的,有时候远程连不上老大的数据库,我就用mysql了。下面我使用oracle数据库。

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>

<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.4.0</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
<!--
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
-->
项目中我们还引入了Axsi2,回头深入了解,先贴个依赖。我写的demo没有用这个。
(2)、配置文件application.properties
当然啦,现在用YAML文件就更直观啦~改天一试,多练练才行,我现在会,但是代码不会敲,全是粘贴,这是个坏习惯!
#配置端口号
server.port=8080

#配置数据源

#mysql
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/test
#spring.datasource.username=root
#spring.datasource.password=root

#oracle
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=root
spring.datasource.password=root
#配置JPA
spring.jpa.database=oracle
#spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
目前show-sql、generate-ddl、ddl-auto值得意思我还不太明白,但是当我们创建表结构的时候一定要用create,灌进数据后千万改成none,不然表新建哦,数据就没了!

(3)、创建五个类:主要根据是将XML分为三部分用于插入数据库和将XML解析成java对象,再将所有标签汇总到一起的一个类。
第一个类:用它来将Bean的内容转换成java对象
import java.util.List;

@Component
@Data
public class Demo {

private List<String> A;

  private List<String> B;
   private List<String> C; 
}
这里,记得添加注解@Component,不然会报错:

  Unable to instantiate deployer org.apache.axis2.deployment.ServiceDeployer; see debug logs for more details

解决:Model层的Key类没有添加注解。
  导致bean无法注入,加一下就行了。和表对应就写@Entity,不对应就写@Component。

问题传送:https://segmentfault.com/q/1010000005957988/a-1020000005958530


 

第二、三个类。Bean中内容对应两张表。
@Entity
@Data
@Table(name = "abtable")
@GenericGenerator(name = "jpa-uuid", strategy = "uuid")
public class ABEntity {

@Id
@GeneratedValue(generator = "jpa-uuid")
@Column(name = "ab_id", length = 32)
private String ab_id;
  @Column(name = "A", length = 200)
  private String A;

  @Column(name = "B", length = 200)
  private String B;

  @OneToMany(cascade={CascadeType.ALL}) //指定一对多关系,级联
  @JoinColumn(name="ab_id",referencedColumnName ="ab_id" )
  private Set<CEntity> emp = new HashSet<CEntity>();
}

import lombok.Data;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;

@Entity
@Data
@Table(name = "ctable")
@GenericGenerator(name = "jpa-uuid", strategy = "uuid")
public class CEntity {

@Id
@GeneratedValue(generator = "jpa-uuid")
@Column(name = "c_id", length = 32)
private String c_id;

@Column(name = "C", length = 200)
private String C;

@Column(name = "ab_id", length = 32)
private String ab_id;
}

第四个类:处理DF两个标签。
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@ToString
@Setter
@Getter
public class DLable{

private String E;

}

第五个类:多个相同的标签封装到一个集合中,有多条Bean,使用集合存储。
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.List;

@ToString
@Setter
@Getter
public class DemoResult {

/**
* 多个相同的标签封装到一个集合中
*/
@XStreamImplicit(itemFieldName = "BEAN")
private List<Demo> BEAN;
private DLable D;
}

接下来再写一个类用于设置XStream
protected XStream getXStream(Class data, Class bean) {
XStream xStream = new XStream() {
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
@Override
public boolean shouldSerializeMember(Class definedIn, String fieldName) {
// 忽略没有的属性
if (definedIn == Object.class) {
return false;
}
return super.shouldSerializeMember(definedIn, fieldName);
}
};
}
};
xStream.alias("DATA", data);
xStream.alias("BEAN", bean);
xStream.addImplicitCollection(PlacePoliceResult.class, "BEAN");
xStream.alias("D, DLable.class);
xStream.alias("A", String.class);
xStream.addImplicitCollection(Demo.class, "A");
xStream.alias("B", String.class);
xStream.addImplicitCollection(Demo.class, "B");
xStream.alias("C", String.class);
xStream.addImplicitCollection(Demo.class, "C");
  return xStream;
}


/**
* 将xml结果封装成java对象,并插入数据库
*
* @throws Exception
*/
这里我们用@Slf4j输出日志。
参数说明:
XStream stream:
  XStream stream = getXStream(DemoResult.class, Demo.class);
String text:
  String text = "<?xml version=”1.0” encoding=”UTF-8”?><Data><Bean><A>a1</A><B>b1</B><C>11</C><A>a1</A><B>b1</B><C>22</C></Bean><Bean><A>a2</A><B>b2</B><C>33</C><A>a2</A><B>b2</B><C>44</C></Bean><D><E></E></D></Data>";
String name:
  String name = Demo.class.getSimpleName();
@Autowired
private CaseInfoDao caseInfoDao;
private void xmlToBeanDemo(XStream stream, String text, String name) {

Object obj = stream.fromXML(text);
if (obj != null) {
List<Map<String, Object>> reslist = new ArrayList<>();
Map<String, Object> resMap = new HashMap<>(16);
List<CEntity> moreList = new ArrayList<CEntity>();

try {
if (obj instanceof DemoResult) {
DemoResult result = (DemoResult) obj;
List<Demo> list = result.getBEAN();
//遍历一的关系
for (int i = 0; i < list.size(); i++) {
moreList = new ArrayList<CEntity>();
resMap = new HashMap<>(16);
Demo demo= list.get(i);
ABEntity aBEntity = new ABEntity();
aBEntity.setA(demo.getA().get(0));
aBEntity.setB(demo.getB().get(0));

resMap.put("ABEntity", aBEntity);
// 遍历多的关系
for (int j = 0; j < demo.getA().size(); j++) {
CEntity cEntity = new CEntity();
cEntity.setC(demo.getC().get(j));

moreList.add(cEntity);
}
resMap.put("moreList", moreList);
reslist.add(resMap);

}
log.info("解析完成。。。");
}
} catch (Exception e) {
log.info("error信息,{}", e.getMessage());
}
caseInfoDao.batchInsertPlace(reslist);
log.info("数据添加完成");
}
log.info("没有数据返回,{}", name);

}

设置将返回的java对象插入数据库
@Slf4j
@Repository
public class CaseInfoDao {

/**
* JPA 实体管理
*/
@PersistenceContext
private EntityManager entityManager;
@Transactional(rollbackFor = Exception.class)
public void batchInsertPlace(List<Map<String,Object>> reslist) {
Map<String,Object> map;
for (int i = 0; i < reslist.size(); i++) {
map = reslist.get(i);
ABEntity aBEntity = (ABEntity)map.get("ABEntity");
//添加实体到session缓存
entityManager.persist(aBEntity);
log.info("ab_id:{}",aBEntity.getAb_id());
List<CEntity> moreList= (List<CEntity>) map.get("moreList");
for (int j = 0; j < moreList.size(); j++) {
CEntity cEntity = moreList.get(j);
cEntity.setAb_id(aBEntity.getAb_id());
log.info("cEntity:{}",cEntity.toString());
entityManager.persist(cEntity);
}
}

entityManager.flush();
log.info("更新数据成功");
//清空缓存
entityManager.clear();
}
}

解析XML并插入数据库:
XStream stream = getXStream(DemoResult.class, Demo.class); 
String text:
  String text = "<?xml version=”1.0” encoding=”UTF-8”?><Data><Bean><A>a1</A><B>b1</B><C>11</C><A>a1</A><B>b1</B><C>22</C></Bean><Bean><A>a2</A><B>b2</B><C>33</C><A>a2</A><B>b2</B><C>44</C></Bean><D><E></E></D></Data>";
String name:
  String name = Demo.class.getSimpleName();
xmlToBeanDemo(stream, text,name);
注意:
以上我还没试验过,过几天反馈。
反思:
  工作时间写博客不对,要多利用课余时间写,总结,多敲多练!写博客时间浪费有点久!继续加油!

以上是关于使用XStream解析复杂XML并插入数据库的主要内容,如果未能解决你的问题,请参考以下文章

XStream解析xml代码

XStream解析XML文本并用反射机制转换为对象

XStream xml 解析框架使用笔记

微信公众号xml数据解析之xstream

Xstream 解析xml文件内容

使用XStream是实现XML与Java对象的转换--Object Stream