java - 如何获取 JPA 实体的列名

标签 java hibernate jpa jakarta-ee reflection

我所有的 JPA 实体类都实现了一个名为 Entity 的接口(interface),其定义如下:

public interface Entity extends Serializable {
// some methods

}

我的 JPA 实体的某些字段顶部有 @Column 注释,有些则没有。 MyEntity 类定义如下:

@Entity
public class MyEntity implements Entity {

   @Id
   private Long id; // Assume that it is auto-generated using a sequence. 

   @Column(name="field1")
   private String field1;


   private SecureString field2; //SecureString is a custom class

   //getters and setters

}

我的删除方法接受一个实体。

@Override
public void delete(Entity baseEntity) {

   em.remove(baseEntity); //em is entityManager
}

每当调用 delete 方法时,我都希望在 delete 方法中包含三样东西:

1) MyEntitySecureString 类型的字段

2) 数据库中该特定字段的列名(该字段可能有也可能没有 @Column 注释)

3)id字段的值

注意当delete()方法被调用时,我们并不知道它是针对哪个实体调用的,可能是针对MyEntity1MyEntity2

我试过做如下的事情:

for (Field field : baseEntity.getClass().getFields()) {
    if (SecureString.class.isAssignableFrom(field.getType())) {
        // But the field doesn't have annotation @Column specified
        Column column = field.getAnnotation(Column.class);

        String columnName = column.name();
    }
}

但这仅在该字段具有 @Column 注释时才有效。它也没有给我其他两件我需要的东西。有什么想法吗?

最佳答案

Hibernate 可以使用不同的naming strategies映射隐式定义的属性名称(没有 @Column(name = "..."))。要获得“物理”名称,您需要深入了解 Hibernate 的内部结构。首先,您必须将 EntityManagerFactory 连接到您的服务。

@Autowired
private EntityManagerFactory entityManagerFactory;

其次,您必须为您的类检索一个AbstractEntityPersister

    SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
    AbstractEntityPersister persister = ((AbstractEntityPersister)sessionFactory.getClassMetadata(baseEntity.getClass()));

第三,您的代码就快完成了。您只需要处理这两种情况 - 使用和不使用 @Column 注释。试试这个:

for (Field field : baseEntity.getClass().getFields()) {
    if (SecureString.class.isAssignableFrom(field.getType())) {
        String columnName;
        if (field.isAnnotationPresent(Column.class)) {
            columnName = field.getAnnotation(Column.class).name();
        } else {
            String[] columnNames = persister.getPropertyColumnNames(field.getName());
            if (columnNames.length > 0) {
                columnName = columnNames[0];
            }
        }
    }
}

请注意,getPropertyColumnNames() 仅检索不属于主键的“属性”字段。要检索键列名称,请使用 getKeyColumnNames()

关于 id 字段。您真的需要在子类中拥有所有@Id 吗?也许最好将@Id 移动到Entity 类并用@MappedSuperclass 注释标记这个类?然后您可以使用 baseEntity.getId();

检索它

关于java - 如何获取 JPA 实体的列名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46335682/

相关文章:

java - 如何在 Spring MVC 中以单一形式编辑两个模型类

java - 如何控制 Java (Jpcap) 中的流量速度(发送的字节数)

java - Eclipse + hibernate 开发。需要生成sql脚本(或创建数据库)的工具

继承所有存储库方法的 Spring Data JPA 全局过滤器子句

java - 为什么 OPTIMISTIC_FORCE_INCREMENT 不增加二级缓存中的版本

在 Windows 和 Linux 中使用 USB 访问的 Java 小程序

java - 嵌套 session /事务中的 Transaction.rollback 会发生什么?

java - 关于mysql、java日期和时区的困惑

java - 我可以在 application.yml 中为实体写入表名吗?

java - MySQL插入字段列表中的未知列