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會報錯