数据访问层注解 JPA/Hibernate 核心注解(实体映射) JPA(Java Persistence API)是 Java 的 ORM 标准,Hibernate 是其最主流的实现,这类注解主要用于将 Java 实体类映射到数据库表 / 列,定义实体关系。
基础映射注解
注解
核心作用
关键参数 / 示例
@Entity
标记类为 JPA 实体,对应数据库中的一张表(必须配合@Id使用)
@Entity public class User { ... }
@Table
自定义实体对应的数据库表信息(省略时表名默认与类名一致)
@Table(name = "t_user", schema = "test")(表名 t_user,库名 test)
@Id
标记字段为实体的主键(必须)
@Id private Long id;
@GeneratedValue
指定主键生成策略(自增、UUID 等)
@GeneratedValue(strategy = GenerationType.IDENTITY)(MySQL 自增)
@Column
自定义字段对应的数据库列信息(省略时列名默认与字段名一致)
@Column(name = "user_name", length = 50, nullable = false)(列名 user_name,长度 50
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Entity @Table(name = "t_user", indexes = {@Index(name = "idx_name", columnList = "user_name")}) public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "user_name", nullable = false, length = 50, unique = true) private String userName; @Column(name = "age", columnDefinition = "int default 18") private Integer age; @Column(name = "email", length = 100, nullable = true) private String email; }
主键生成策略说明
策略
适用场景
IDENTITY
MySQL、PostgreSQL 等支持自增列的数据库(推荐)
SEQUENCE
Oracle、DB2 等支持序列的数据库(需配合@SequenceGenerator)
TABLE
所有数据库(通过中间表生成主键,性能差,不推荐)
AUTO
由 JPA 自动选择策略(跨数据库时用)
关联关系注解(一对一 / 一对多 / 多对多) 用于定义实体间的关联关系(对应数据库的外键),核心是维护对象模型与关系模型的映射。
注解
作用 核心参数
@OneToOne
一对一关联(如 User ↔ UserDetail)
@OneToMany
一对多关联(如 User ↔ Order)
@ManyToOne
多对一关联(如 Order ↔ User)
@ManyToMany
多对多关联(如 User ↔ Role)
示例 1:一对多(User ↔ Order)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Entity @Table(name = "t_user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String userName; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List<Order> orders = new ArrayList <>(); } @Entity @Table(name = "t_order") public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String orderNo; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "user_id") private User user; }
示例 2:多对多(User ↔ Role)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 @Entity @Table(name = "t_user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String userName; @ManyToMany @JoinTable( name = "t_user_role", // 中间表名 joinColumns = @JoinColumn(name = "user_id"), // 当前实体外键 inverseJoinColumns = @JoinColumn(name = "role_id") // 关联实体外键 ) private Set<Role> roles = new HashSet <>(); } @Entity @Table(name = "t_role") public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String roleName; @ManyToMany(mappedBy = "roles") private Set<User> users = new HashSet <>(); }
Spring Data JPA 注解(数据访问层) @Repository - 数据访问层标 作用:标记接口 / 类为数据访问层(DAO) 组件,Spring 会自动扫描并注册为 Bean,同时会将数据访问异常转换为 Spring 统一的DataAccessException。
举例:
1 2 3 4 5 6 @Repository public interface UserRepository extends JpaRepository <User, Long> { User findByUserName (String userName) ; }
注意:
Spring Data JPA 的 Repository 接口(如JpaRepository/CrudRepository)无需手动加@Repository,Spring 会自动识别;
非 Spring Data JPA 的自定义 DAO 实现类,需加@Repository让 Spring 扫描。
@Query - 自定义 JPQL/SQL 查询 作用:在 Repository 方法上自定义查询语句(JPQL 或原生 SQL),替代 “方法名解析” 的局限性,支持动态参数。
关键参数
参数
作用
value
查询语句(JPQL 或 SQL)
nativeQuery
是否为原生 SQL(默认 false,JPQL)
countQuery
分页查询时的总数查询语句
示例 1:JPQL 查询(面向实体)
1 2 3 4 5 6 7 8 public interface UserRepository extends JpaRepository <User, Long> { @Query("SELECT u FROM User u WHERE u.userName LIKE %:name% AND u.age > :age") List<User> findByUserNameLikeAndAgeGreaterThan (@Param("name") String name, @Param("age") Integer age) ; }
示例 2:原生 SQL 查询(面向表)
1 2 3 4 5 6 7 8 9 10 11 public interface UserRepository extends JpaRepository <User, Long> { @Query(value = "SELECT * FROM t_user WHERE email = ?1", nativeQuery = true) User findByEmail (String email) ; @Query(value = "SELECT * FROM t_user WHERE age BETWEEN ?1 AND ?2", countQuery = "SELECT COUNT(*) FROM t_user WHERE age BETWEEN ?1 AND ?2", nativeQuery = true) Page<User> findByAgeBetween (Integer minAge, Integer maxAge, Pageable pageable) ; }
@Modifying - 标记修改型查询 作用:配合@Query使用,标记该查询是增 / 删 / 改操作(非查询),需配合@Transactional使用。
举例:
1 2 3 4 5 6 7 8 9 10 11 public interface UserRepository extends JpaRepository <User, Long> { @Modifying @Query("UPDATE User u SET u.age = :age WHERE u.id = :id") int updateAgeById (@Param("id") Long id, @Param("age") Integer age) ; @Modifying @Query("DELETE FROM User u WHERE u.userName = :name") void deleteByUserName (@Param("name") String name) ; }
注意
返回值:增删改操作可返回int(受影响行数)或void;
必须在方法或类上添加@Transactional,否则抛TransactionRequiredException。
@Transactional - 事务管理 作用:标记方法 / 类需要事务支持,Spring 会自动为该方法开启、提交 / 回滚事务,是数据操作的核心注解。
关键参数
参数
作用
默认值
readOnly
是否为只读事务(查询操作建议设为 true,优化性能)
false
rollbackFor
指定触发回滚的异常类型(默认仅 RuntimeException 回滚)
无
propagation
事务传播行为(如 REQUIRED、REQUIRES_NEW)
REQUIRED
isolation
事务隔离级别(如 READ_COMMITTED、REPEATABLE_READ)
数据库默认
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Service public class UserService { @Autowired private UserRepository userRepository; @Transactional(readOnly = true) public User getUserById (Long id) { return userRepository.findById(id).orElse(null ); } @Transactional(rollbackFor = Exception.class) public void updateUser (User user) { userRepository.save(user); if (user.getAge() < 0 ) { throw new IllegalArgumentException ("年龄不能为负数" ); } } }
MyBatis 核心注解(数据访问) @Mapper - MyBatis 映射器 作用:标记接口为MyBatis Mapper 接口,MyBatis 会动态生成该接口的实现类,Spring 可自动扫描并注入。
两种启用方式
方式 1:每个 Mapper 接口加@Mapper;
方式 2:主启动类加@MapperScan(“com.example.demo.mapper”)(批量扫描,推荐)。
举例1:
1 2 3 4 5 6 7 @Mapper public interface UserMapper { @Select("SELECT * FROM t_user WHERE id = #{id}") User selectById (Long id) ; }
举例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 @SpringBootApplication @MapperScan("com.example.demo.mapper") public class DemoApplication { public static void main (String[] args) { SpringApplication.run(DemoApplication.class, args); } } public interface UserMapper { @Select("SELECT * FROM t_user WHERE id = #{id}") User selectById (Long id) ; }
@Select/@Insert/@Update/@Delete - SQL 注解 作用:直接在 Mapper 方法上定义查询 / 插入 / 更新 / 删除的 SQL 语句,替代 XML 中的/等标签。
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Mapper public interface UserMapper { @Select("SELECT id, user_name as userName, age, email FROM t_user WHERE id = #{id}") User selectById (Long id) ; @Insert("INSERT INTO t_user(user_name, age, email) VALUES (#{userName}, #{age}, #{email})") @Options(useGeneratedKeys = true, keyProperty = "id") int insert (User user) ; @Update("UPDATE t_user SET user_name = #{userName}, age = #{age} WHERE id = #{id}") int update (User user) ; @Delete("DELETE FROM t_user WHERE id = #{id}") int deleteById (Long id) ; @Select("SELECT * FROM t_user WHERE user_name LIKE CONCAT('%', #{name}, '%') AND age > #{age}") List<User> selectByCondition (@Param("name") String name, @Param("age") Integer age) ; }