java 如何获取 JPA 实体的列名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46335682/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:10:00  来源:igfitidea点击:

How to get Column names of JPA entity

javahibernatejpajakarta-eereflection

提问by Aman

All my JPA entity classes implement an interface called Entity which is defined like this:

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

public interface Entity extends Serializable {
// some methods

}

Some of the fields of my JPA entity have @Columnannotation on top of them and some don't. MyEntityclass is defined like below:

我的 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

}

My delete method accepts an Entity.

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

@Override
public void delete(Entity baseEntity) {

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

Whenever the delete method is invoked I want three things inside my delete method:

每当调用 delete 方法时,我都希望在 delete 方法中包含三件事:

1) Fields of MyEntitythat are of type SecureString

1)MyEntity属于类型的字段SecureString

2) Column name of that particular field in DB (The field may or may not have @Columnannotation)

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

3) The value of idfield

3)id字段值

Note that when the delete()method is invoked, we don't know for which entity it is invoked, it may be for MyEntity1, MyEntity2etc.

请注意,当delete()方法被调用时,我们不知道哪个实体调用它,它可能是MyEntity1MyEntity2等等。

I have tried doing something like below:

我试过做类似下面的事情:

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();
    }
}

But this will only work if the field has @Columnannotation. Also it doesn't get me other two things that I need. Any ideas?

但这只有在该字段有@Column注释时才有效。它也没有让我得到我需要的其他两件事。有任何想法吗?

回答by Anatoly Shamov

Hibernate can use different naming strategiesto map property names, which are defined implicitly (without @Column(name = "...")). To have a 'physical' names you need to dive into Hibernate internals. First, you have to wire an EntityManagerFactoryto your service.

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

@Autowired
private EntityManagerFactory entityManagerFactory;

Second, you have to retrieve an AbstractEntityPersisterfor your class

其次,你必须AbstractEntityPersister为你的班级检索一个

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

Third, you're almost there with your code. You just have to handle both cases - with and without @Column annotation. Try this:

第三,您的代码就快完成了。您只需要处理这两种情况 - 有和没有 @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];
            }
        }
    }
}

Note that getPropertyColumnNames()retrieves only 'property' fields, that are not a part of primary key. To retrieve key column names, use getKeyColumnNames().

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

And about idfield. Do you really need to have all @Id's in child classes? Maybe would better to move @Id to Entityclass and mark this class with @MappedSuperclass annotation? Then you can retrieve it just with baseEntity.getId();

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