博客 / 詳情

返回

Spring Boot JPA:簡介、註解與查詢方法

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

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.