JPA 是什麼
Java Persistence API(JPA)是Java EE的一部分,用於簡化Java應用程序中的數據持久化操作。Spring Boot框架集成了JPA,提供了一種方便的方式來進行對象關係映射(ORM),將Java對象映射到數據庫表中。這使得開發者能夠通過使用Java類和註解,而不是繁瑣的SQL語句,來進行數據庫操作。
JPA 的註解
實體類相關注解
@Entity
將Java類標記為JPA實體,用於映射到數據庫表。
@Entity
public class User {
// 其他字段或方法
}
@Table
用於指定實體類與數據庫表的映射關係,可以指定表的名稱等信息。
@Entity
@Table(name = "users")
public class User {
// 其他字段或方法
}
如果沒有 @Table 註解以設置表名的話,則以類名為表名,且大小寫敏感。
主鍵相關注解
@Id
定義實體類的主鍵字段。
@Entity
public class User {
@Id
private Long id;
// 其他字段或方法
}
@GeneratedValue
定義主鍵的生成策略。
@Entity
public class User {
@Id
// 設置主鍵的自增策略
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 其他字段或方法
}
字段與列的映射註解
@Column
用於定義實體類字段與數據庫表列的映射關係。可以指定列的名稱、長度、是否允許為null等屬性。
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", length = 50, nullable = false)
private String username;
// 其他字段或方法
}
@Transient
表示該字段不需要持久化到數據庫。
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Transient
private transientField; // Will not be persisted to the database
// 其他字段或方法
}
關係映射註解
@OneToOne
@OneToMany
@ManyToOne
@ManyToMany
@JoinColumn
查詢相關注解
@Query
用於定義JPQL或原生SQL查詢。
@Entity
public class Product {
@Id
private Long id;
private String name;
private double price;
// 其他字段或方法
}
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
// 使用JPQL查詢所有產品
@Query("SELECT p FROM Product p")
List<Product> findAllProducts();
// 使用JPQL查詢價格低於指定值的產品
@Query("SELECT p FROM Product p WHERE p.price < :maxPrice")
List<Product> findProductsByPrice(@Param("maxPrice") double maxPrice);
}
@NamedQuery
用於定義命名查詢。
@Entity
@NamedQuery(name = "Product.findByProductName", query = "SELECT p FROM Product p WHERE p.productName = :productName")
public class Product {
// 其他字段或方法
}
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
@Query(name = "Product.findByProductName")
Product findByProductName(@Param("productName") String productName);
}
@NamedQueries
用於定義一組命名查詢。
@Entity
@NamedQueries({
@NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p"),
@NamedQuery(name = "Product.findByPrice", query = "SELECT p FROM Product p WHERE p.price < :maxPrice")
})
public class Product {
@Id
private Long id;
private String name;
private double price;
// 其他字段或方法
}
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
@Query(name = "Product.findAll")
List<Product> findAllProducts();
@Query(name = "Product.findByPrice")
List<Product> findProductsByPrice(@Param("maxPrice") double maxPrice);
}
版本控制註解
@Version
確保在併發環境下對實體的修改是線程安全的。它通常與整數類型的字段一起使用,該字段在每次更新時遞增,從而允許檢測併發更新衝突。
@Entity
public class Product {
@Id
private Long id;
private String name;
private double price;
@Version
private int version; // 樂觀鎖版本控制字段
// 其他字段或方法
}
生命週期回調註解
@PrePersist
在實體被持久化前調用的方法。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@PrePersist
public void prePersist() {
// 一些邏輯
}
// 其他字段或方法
}
@PostPersist
在實體被持久化後調用的方法。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@PostPersist
public void postPersist() {
// 一些邏輯
}
// 其他字段或方法
}
@PreUpdate
在實體被更新前調用的方法。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@PreUpdate
public void preUpdate() {
// 一些邏輯
}
// 其他字段或方法
}
@PostUpdate
在實體被更新後調用的方法。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@PostUpdate
public void postUpdate() {
// 一些邏輯
}
// 其他字段或方法
}
@PreRemove
在實體被刪除前調用的方法。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@PreRemove
public void preRemove() {
// 一些邏輯
}
// 其他字段或方法
}
@PostRemove
在實體被刪除後調用的方法。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@PostRemove
public void postRemove() {
// 一些邏輯
}
// 其他字段或方法
}
除了上述提到的註解,JPA還有其他註解:
繼承映射註解 @MappedSuperclass、枚舉映射註解 @Enumerated、Lob註解 @Lob、表的索引相關注解 @Index 等等。
這裏不過多深入。
JPA 的查詢方法
基於方法名稱的查詢
我們最常用的查詢方法。能夠覆蓋絕大部分查詢需求。
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
User findByUsernameAndEmail(String username, String email);
List<User> findByEmailLike(String email);
}
JPQL查詢(@Query、@NamedQuery、@NamedQueries註解)
用法與上文中的註解中的示例相同。
JPQL與SQL語句存在一些細微的差別,可以理解為方言。具體情況用到時再查看文檔即可。
Native SQL查詢(@Query)
@Query(value = "SELECT * FROM users WHERE username = ?1", nativeQuery = true)
User findByNativeQuery(String username);
動態查詢
使用Criteria API進行動態查詢。
它提供了一種基於類型安全的查詢機制,允許開發者以面向對象的方式構建查詢條件,而不必編寫字符串形式的 JPQL(Java Persistence Query Language)查詢語句。
Criteria API 基本用法:
// 自定義的動態查詢方法
@Override
public List<Product> findProductsByCriteria(String name) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Product> query = criteriaBuilder.createQuery(Product.class);
Root<Product> root = query.from(Product.class);
// 添加查詢條件
Predicate condition = criteriaBuilder.equal(root.get("name"), name);
query.where(condition);
// 執行查詢
List<Product> products = entityManager.createQuery(query).getResultList();
}
動態查詢:
public class ProductRepositoryCustomImpl implements ProductRepositoryCustom {
// 自定義的動態查詢方法
@Override
public List<Product> findProductsByCriteria(String name, Double maxPrice) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Product> query = criteriaBuilder.createQuery(Product.class);
Root<Product> root = query.from(Product.class);
List<Predicate> conditions = new ArrayList<>();
// 動態添加查詢條件
if (name != null && !name.isEmpty()) {
conditions.add(criteriaBuilder.equal(root.get("name"), name));
}
if (maxPrice != null) {
conditions.add(criteriaBuilder.lessThanOrEqualTo(root.get("price"), maxPrice));
}
// 構建查詢條件
query.where(conditions);
// 執行查詢
return entityManager.createQuery(query).getResultList();
}
}
希望這篇文章對你有幫助!
參考資料
https://docs.spring.io/spring-data/jpa/reference/jpa.html