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 {
// 使用JPQL查询所有产品
@Query("SELECT p FROM Product p")
List findAllProducts();
// 使用JPQL查询价格低于指定值的产品
@Query("SELECT p FROM Product p WHERE p.price < :maxPrice")
List 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 {
@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 {
@Query(name = "Product.findAll")
List findAllProducts();
@Query(name = "Product.findByPrice")
List 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 findByUsername(String username);
User findByUsernameAndEmail(String username, String email);
List 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 findProductsByCriteria(String name) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery query = criteriaBuilder.createQuery(Product.class);
Root root = query.from(Product.class);
// 添加查询条件
Predicate condition = criteriaBuilder.equal(root.get("name"), name);
query.where(condition);
// 执行查询
List products = entityManager.createQuery(query).getResultList();
}
动态查询:
public class ProductRepositoryCustomImpl implements ProductRepositoryCustom {
// 自定义的动态查询方法
@Override
public List findProductsByCriteria(String name, Double maxPrice) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery query = criteriaBuilder.createQuery(Product.class);
Root root = query.from(Product.class);
List 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();
}
}
希望这篇文章对你有帮助!