0

0

JPA 中 @Access 注解的混合访问模式详解与验证实践

霞舞

霞舞

发布时间:2026-02-07 16:38:06

|

605人浏览过

|

来源于php中文网

原创

JPA 中 @Access 注解的混合访问模式详解与验证实践

本文深入解析 jpa 的 `@access` 注解如何在单个实体中混合使用 field 和 property 访问策略,并通过可运行的单元测试验证字段直写与属性拦截(getter/setter 调用)的实际行为差异。

在 JPA 规范中,实体属性的访问方式默认由 @Id 注解的位置决定:若 @Id 标注在字段上,则整个实体采用 AccessType.FIELD(直接读写私有字段);若标注在 getter 方法上,则采用 AccessType.PROPERTY(通过 getter/setter 访问)。但 JPA 同时支持细粒度控制——通过 @Access(AccessType.PROPERTY) 或 @Access(AccessType.FIELD) 显式覆盖单个属性的访问策略,从而实现同一实体内“字段直写 + 属性拦截”的混合访问模式。

关键在于:

  • 未被 @Access 显式修饰的属性,继承实体级默认访问类型(本例中因 @Id 在字段上,默认为 FIELD);
  • 被 @Access(AccessType.PROPERTY) 修饰的属性(如 lastName),强制 JPA 通过其 getter/setter 进行读写,即使其他属性走字段直写路径。

以下是一个精简、可验证的完整示例:

@Entity
public class Student {
    @Id
    @GeneratedValue
    private Long ID;

    // 默认 FIELD 访问:JPA 直接读写 firstName 字段,绕过 setFirstName/getFirstName
    private String firstName;

    // 显式 PROPERTY 访问:JPA 必须调用 setLastName/getlastName(注意方法名拼写需正确!)
    @Access(AccessType.PROPERTY)
    private String lastName;

    // 正确的 getter/setter 命名(原问题中 getlastName 拼写错误,应为 getLastName)
    public String getFirstName() {
        System.out.println("~~~~~~~~getFirstName~~~~~~~~~"); // ✅ 不会被 JPA 调用(FIELD 模式)
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = "FirstName: " + firstName; // ✅ 不会被 JPA 调用
        System.out.println("~~~~~~~~setFirstName~~~~~~~~~");
    }

    public String getLastName() { // 修正:方法名应为 getLastName
        System.out.println("~~~~~~~~getLastName~~~~~~~~~"); // ✅ JPA 会调用此 getter(PROPERTY 模式)
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = "LastName: " + lastName; // ✅ JPA 会调用此 setter
        System.out.println("~~~~~~~~setLastName~~~~~~~~~");
    }
}
⚠️ 注意事项: @Access 仅对紧邻的下一个属性或方法生效,且必须与目标属性的声明位置一致(如修饰字段,则 getter/setter 必须存在且命名规范); getter/setter 方法名必须严格遵循 JavaBean 规范(如 getLastName,而非 getlastName),否则 JPA 无法识别; 混合访问时,@Id 仍需保持唯一性,且其访问方式(FIELD/PROPERTY)决定默认策略,不可冲突; 实际持久化行为需通过数据库实际值和日志输出双重验证,而非仅依赖 IDE 调试断点。

下面的单元测试可明确证明混合访问效果:

法语写作助手
法语写作助手

法语助手旗下的AI智能写作平台,支持语法、拼写自动纠错,一键改写、润色你的法语作文。

下载
@Test
public void testAccessAnnotation() {
    Student student = new Student();
    student.setFirstName("John");      // 手动调用,仅影响内存对象
    student.setLastName("Doe");        // 手动调用,仅影响内存对象

    entityManager.getTransaction().begin();
    entityManager.persist(student);      // JPA 持久化:firstName 直写字段 → 存 "John";lastName 调用 setter → 存 "LastName: Doe"
    entityManager.getTransaction().commit();
    entityManager.clear();

    // 重新加载实体
    Student loaded = entityManager.find(Student.class, student.getID());

    // 验证结果:
    // - firstName 未经过 setter,数据库存的是原始值 "John"
    assertEquals("John", loaded.getFirstName()); 
    // - lastName 经过 setter 处理,数据库存的是 "LastName: Doe"
    assertEquals("LastName: Doe", loaded.getLastName()); 
}

运行该测试时,控制台将输出两行 ~~~~~~~~setLastName~~~~~~~~~(分别对应 persist 和 find 时的 setter 调用),而 ~~~~~~~~setFirstName~~~~~~~~~ 不会出现——这正是 @Access 精准控制访问路径的直接证据。

总结而言,@Access 是 JPA 提供的高级机制,适用于需要对特定字段实施业务逻辑封装(如自动加前缀、加密、审计赋值)而不影响其他字段性能的场景。合理使用它,既能保持代码清晰性,又能精准控制数据生命周期中的拦截时机。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

362

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2088

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

352

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

256

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

327

2023.10.09

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

414

2023.10.16

vb连接access数据库的方法
vb连接access数据库的方法

vb连接access数据库方法:1、使用ADO连接,首先导入System.Data.OleDb模块,然后定义一个连接字符串,接着创建一个OleDbConnection对象并使用Open() 方法打开连接;2、使用DAO连接,首先导入 Microsoft.Jet.OLEDB模块,然后定义一个连接字符串,接着创建一个JetConnection对象并使用Open()方法打开连接即可。

420

2023.10.16

vb连接数据库的方法
vb连接数据库的方法

vb连接数据库的方法有使用ADO对象库、使用OLEDB数据提供程序、使用ODBC数据源等。详细介绍:1、使用ADO对象库方法,ADO是一种用于访问数据库的COM组件,可以通过ADO连接数据库并执行SQL语句。可以使用ADODB.Connection对象来建立与数据库的连接,然后使用ADODB.Recordset对象来执行查询和操作数据;2、使用OLEDB数据提供程序方法等等。

227

2023.10.19

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

2

2026.02.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.3万人学习

C# 教程
C# 教程

共94课时 | 8.7万人学习

Java 教程
Java 教程

共578课时 | 59.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号