6

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


HHepan
164 声望13 粉丝

河北工业大学