<dependencies> <!-- Spring 核心 --> <dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>4.0.5.RELEASE</version></dependency> <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.0.5.RELEASE</version></dependency> <dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>4.0.5.RELEASE</version></dependency> <!-- JUnit --> <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency> <!-- Hibernate 作為 JPA Provider --> <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>4.3.1.Final</version></dependency> <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>4.3.1.Final</version></dependency> <!-- MySQL 驅動 --> <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.31</version></dependency> </dependencies>
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="https://java.sun.com/xml/ns/persistence"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/persistence https://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="myJPA" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.domain.User</class>
<class>com.domain.Driver</class>
<class>com.domain.Car</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="000"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF-8"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="javax.persistence.validation.mode" value="none"/>
</properties>
</persistence-unit>
</persistence>
關鍵說明:
transaction-type="RESOURCE_LOCAL":本地事務,非 JTAhbm2ddl.auto=update:自動更新表結構,開發環境適用LocalContainerEntityManagerFactoryBean 替代 persistence.xml@Entity
@Table(name = "driver")
public class Driver {
@Id @GeneratedValue
private Long id;
@Column(name = "firstname")
private String firstName;
@Column(name = "lastname")
private String lastName;
@OneToMany(cascade = CascadeType.ALL) // 傳播性持久化
@JoinColumn(name = "driver_id")
private Set<Car> cars = new HashSet<>();
// getter/setter/toString 省略...
}
@Entity
@Table(name = "car")
public class Car {
@Id @GeneratedValue
private Long id;
@Column(name = "name")
private String name;
// getter/setter/toString 省略...
}
關鍵註解:cascade=CascadeType.ALL 表示持久化 Driver 時自動級聯持久化關聯的 Car 集合。
@Test
public void openTest() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myJPA");
System.out.println("工廠開啟狀態:" + emf.isOpen());
}
@Test
public void addTest() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myJPA");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Driver driver = new Driver();
driver.setFirstName("Taylor");
driver.setLastName("Swift");
Car car1 = new Car(); car1.setName("BMW");
Car car2 = new Car(); car2.setName("AUDI");
driver.getCars().add(car1);
driver.getCars().add(car2);
em.persist(driver); // 級聯持久化 cars
tx.commit();
em.close();
}
@Test
public void findTest() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myJPA");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
// find:立即查詢,無結果返回 null
Driver driver = em.find(Driver.class, 1L);
// getReference:延遲載入(可能拋出 EntityNotFoundException)
Car car = em.getReference(Car.class, 2L);
driver.setFirstName("Justin"); // 髒數據自動檢測,提交時更新
em.remove(car); // 刪除
tx.commit();
em.close();
}
JPA 追蹤所有由 EntityManager 載入的實體。實體狀態變更會被標記為「髒數據」,提交事務時自動執行 UPDATE。前提:實體處於「受管狀態」(關聯有效的 EntityManager)。
// 合併游離實體回受管態 Driver managedDriver = em.merge(detachedDriver);
下篇將介紹 Spring Data JPA:以 JpaRepository 介面替代樣板代碼,實現零代碼 CRUD、分頁查詢、規範查詢等進階功能。