XML解析與JPA

1、xml解析

xml解析總共有四種方式,我在這里只介紹兩種方式:原生的和使用dom4j的方式

students.xml

<students>
    <student>
        <id>1</id>
        <name>mike</name>
        <age>20</age>
    </student>
    <student>
        <id>2</id>
        <name>tom</name>
        <age>22</age>
    </student>
    <student>
        <id>3</id>
        <name>jerry</name>
        <age>21</age>
    </student>
    <student>
        <id>4</id>
        <name>linda</name>
        <age>18</age>
    </student>
</students>

這個xml文件中定義了5個student對象

Student.java

package com.qianfeng;

public class Student {
    private int id;

    private String name;

    private int age;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Student{");
        sb.append("id=").append(id);
        sb.append(", name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append('}');
        return sb.toString();
    }
}

這是一個pojo

XMLTest.java

package com.qianfeng;

import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class XMLTest {

    private List<Student> parseXML(String path){
        List<Student> list = new ArrayList<>();
        //1、獲取工廠
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            //2、獲取builder
            DocumentBuilder builder = dbf.newDocumentBuilder();
            //3、解析xml文件
            Document document = builder.parse(path);
            //4、獲得節(jié)點
            NodeList students = document.getElementsByTagName("student");
            Student stu = null;
            for (int i = 0; i < students.getLength(); i++) {
                stu = new Student();
                Node item = students.item(i);
                NodeList nodes = item.getChildNodes();
                for (int j = 0; j < nodes.getLength() ; j++) {
                    Node node = nodes.item(j);
                    switch (node.getNodeName()){
                        case "id":
                            String sid = node.getTextContent();
                            int id = sid == null ? 0:Integer.parseInt(sid);
                            stu.setId(id);
                            break;
                        case "name":
                            String name = node.getTextContent();
                            stu.setName(name);
                            break;
                        case "age":
                            String sage = node.getTextContent();
                            int age = sage == null ? 0:Integer.parseInt(sage);
                            stu.setAge(age);
                            break;
                    }
                    list.add(stu);
                }
            }
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
        return list;
    }
    @Test
    public void testParseXML(){
        //System.out.println(parseXML("students.xml"));
        System.out.println(parseXMLByDOM4J("students.xml"));
    }

    private List<Student> parseXMLByDOM4J(String path){
        List<Student> list = new ArrayList<>();
        //1、獲取SAXReader
        SAXReader reader = new SAXReader();
        Student student = null;
        try {
            //2、通過reader讀取文件
            org.dom4j.Document document = reader.read(path);
            //3、獲取document獲取根元素
            Element rootElement = document.getRootElement();
            List<Element> elements = rootElement.elements();
            for (Element element : elements) {
                student = new Student();
                List<Element> elements1 = element.elements();
                for (Element e : elements1) {
                    switch (e.getName()){
                        case "id":
                            String sid = e.getText();
                            int id = sid == null ? 0:Integer.parseInt(sid);
                            student.setId(id);
                            break;
                        case "name":
                            String name = e.getText();
                            student.setName(name);
                            break;
                        case "age":
                            String sage =e.getText();
                            int age = sage == null ? 0:Integer.parseInt(sage);
                            student.setAge(age);
                            break;
                    }
                    list.add(student);
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return list;
    }
}

這是測試類,parseXML(String path)方法使用的是Java原生的方式,parseXMLByDOM4J(String path)這個方法使用的是dom4j的方式,這種方式需要在pom.xml文件中添加一個dom4j的依賴。

<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>

2、JPA

JPA(Java Persistence API)是Java持久層API,是一套Sun公司制定的ORM方案,是一套規(guī)范,也是一套標(biāo)準(zhǔn),sun公司自己并沒有實現(xiàn)。JPA是面向?qū)ο蟮亩皇敲嫦驍?shù)據(jù)庫的,所以JPA不需要自己編寫SQL語句,由框架自動產(chǎn)生SQL語句。核心概念:

  • 實體(pojo)表示關(guān)系數(shù)據(jù)庫中的一個表

  • 每個實體實例對應(yīng)著該表中的一行

  • 類必須用javax.persistence.Entity注解

  • 類必須含有一個public或者protected的無參構(gòu)造函數(shù)

  • 當(dāng)實體實例被當(dāng)做值以分離對象的方式進(jìn)行傳遞(例如通過會話bean的遠(yuǎn)程業(yè)務(wù)接口)則該類必須實現(xiàn)Serializable(序列化)接口

  • 唯一的對象標(biāo)志符,簡單主鍵(javax.persistence.Id),復(fù)合主鍵(javax.persistence.EmbeddledId和javax.persistence.IdClass)

關(guān)系:

  • 一對一:@OneToOne
  • 一對多:@OneToMany
  • 多對一:@ManyToOne
  • 多對多:@ManyToMany

四種狀態(tài):

  • 瞬時態(tài)
  • 持久態(tài)
  • 游離態(tài)
  • 刪除態(tài)

2.1 添加依賴

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>0401</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.2.3.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.4.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
            <scope>test</scope>
        </dependency>

    </dependencies>
</project>

這里實際上只需要添加hibernate與jpa兩個依賴,最后一個依賴是為了解決在項目運行過程中出現(xiàn)的"Failed to load class "org.slf4j.impl.StaticLoggerBinder""錯誤。需要注意,我這里使用的hibernate與jpa版本較高,操作方式與低版本的操作方式有些不一樣,稍后會講。

spring-jpa.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
    
    <context:property-placeholder location="classpath:db.properties"/>

    <context:component-scan base-package="com.qianfeng.service"/>
    <context:component-scan base-package="com.qianfeng.dao"/>
    <!--配置druid數(shù)據(jù)源-->
    <bean id="ds" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${url}"/>
        <property name="driverClassName" value="${driver}"/>
        <property name="username" value="${user}"/>
        <property name="password" value="${pass}"/>
    </bean>
    <!--配置適配器,用來設(shè)置數(shù)據(jù)庫方言以及是否需要顯示SQL語句-->
    <bean id="adapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
        <property name="showSql" value="true"/>
    </bean>
    
    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="ds"/>
        <property name="packagesToScan" value="com.qianfeng.entity"/>
        <property name="jpaVendorAdapter" ref="adapter"/>
        <property name="jpaProperties">
            <props>
                  <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>
    <!--配置JPA的事務(wù)管理器-->
    <bean id="jtx" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="emf"/>
    </bean>
    <!--配置事務(wù)的注解驅(qū)動-->
    <tx:annotation-driven proxy-target-class="false" transaction-manager="jtx"/>

    <jpa:repositories base-package="com.qianfeng.dao" entity-manager-factory-ref="emf" transaction-manager-ref="jtx"/>
</beans>

這是jpa的配置文件,這個配置文件和之前的spring-mybatis的配置文件很像,使用JPA后就不用mybatis了,兩者可以相互取代。這個配置文件中配置了druid數(shù)據(jù)源、HibernateJpa適配器、實體管理工廠、jpa的事務(wù)管理、注解驅(qū)動以及jpa的repositories。

Product.java

package com.qianfeng.entity;

import javax.persistence.*;

@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private double price;
    private int type;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getType() {
        return type;
    }

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

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Product{");
        sb.append("id=").append(id);
        sb.append(", name='").append(name).append('\'');
        sb.append(", price=").append(price);
        sb.append(", type=").append(type);
        sb.append('}');
        return sb.toString();
    }
}

這個類位于entity包下,使用了@Entity和@Table注解,@Entity注解表明這是一個實體,要被管理,@Table注解對應(yīng)的數(shù)據(jù)庫的表,@Id注解表示這是一個主鍵,@GeneratedValue表明生成方式,由于我使用的自增,所以生成策略是GenerationType.IDENTITY。我在這里沒有使用@Column注解,因為我的數(shù)據(jù)庫表中的字段和Entity中的字段名相同,如果不同就需要使用這個注解。

ProductServiceImpl.java

package com.qianfeng.service.impl;

import com.qianfeng.dao.IProductDao;
import com.qianfeng.entity.Product;
import com.qianfeng.service.IProductService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
@Service
public class ProductServiceImpl implements IProductService {

    @Resource
    private IProductDao productDao;
    @Override
    public List<Product> getAllProducts() {
        return productDao.findAll();
    }

    @Override
    public Product findOneProductById(int pid) {
        return productDao.findById(pid).orElse(null);
    }

    @Override
    public Product getOneProductById(int pid) {
        return productDao.findById(pid).get();
    }

    @Override
    public Product saveProduct(Product product) {
        return productDao.saveAndFlush(product);
    }

    @Override
    public void deleteProductById(int pid) {
        productDao.deleteById(pid);
    }
}

這個類實現(xiàn)了自定義的IProductService接口,打了@Service注解。有些地方需要說明,由于JPA版本的更迭,之前可以直接使用return productDao.findById(pid)?,F(xiàn)在可以在后面加上orElse(null)表示否則返回null,這是因為返回值更改了。此外,getOne()方法一直出現(xiàn)延遲加載報錯no session的問題,這也是因為版本更迭,新版本中需要使用findById().get()這個方法。在JPA中,數(shù)據(jù)庫的修改和增加合并了,可以使用savaAndFlush()方法完成這兩個操作:如果不提供主鍵就是新增;如果提供主鍵,但是主鍵已經(jīng)存在就是修改,主鍵不存在就是新增。

IProductDao.java

package com.qianfeng.dao;

import com.qianfeng.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
@Repository
public interface IProductDao extends JpaRepository<Product, Serializable> {
}

這個接口繼承了JpaRepository接口,而繼承了PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>,前者又繼承了CrudRepository<T, ID>接口。

package com.qianfeng;

import com.qianfeng.entity.Product;
import com.qianfeng.service.IProductService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-jpa.xml")
public class TestProduct {
    @Resource
    private IProductService productService;
    @Test
    public void testGetAll(){
        System.out.println(productService.getAllProducts());
    }
    @Test
    public void testFindOne(){
        System.out.println(productService.findOneProductById(10));
    }

    @Test
    public void testGetOne(){
        System.out.println(productService.getOneProductById(100));
    }
    @Test
    public void testSaveProductNoKey(){
        Product product = new Product();
        product.setName("N95口罩");
        product.setPrice(100);
        product.setType(1);
        Product product1 = productService.saveProduct(product);
        System.out.println(product1);
    }

    @Test
    public void testSaveProductExitsKey(){
        Product product = new Product();
        product.setId(1);
        product.setName("N95口罩");
        product.setPrice(100);
        product.setType(1);
        Product product1 = productService.saveProduct(product);
        System.out.println(product1);
    }

    @Test
    public void testSaveProductNotExitsKey(){
        Product product = new Product();
        product.setId(10);
        product.setName("N95口罩");
        product.setPrice(100);
        product.setType(1);
        Product product1 = productService.saveProduct(product);
        System.out.println(product1);
    }

    @Test
    public void testDeleteProduct(){
        productService.deleteProductById(7);
    }
}
  • findOne()與getOne()的區(qū)別:
    • findOne返回一個實體類,getOne返回一個實體類的引用;
    • 如果要查詢的對象不存在,findOne不會報錯,getOne會報錯
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容