在 Spring Data JPA 中,是否有任何最简单的方法来获取 Table 元数据(列名列表)信息?我可以在通用数据库上使用哪个
Is there any Simplest way to get Table metadata (column name list) information, in Spring Data JPA ? which could I use on universal database
我想使用 spring 数据 jpa 获取所有 table 的列列表,我的数据库很灵活,所以查询应该适用于所有类型的数据库.
JPA 规范包含元模型 API,它允许您查询有关托管类型及其托管字段的信息。但是,它不涵盖底层数据库。因此,JPA 中还没有开箱即用的东西来查询数据库元数据。
每个 RDBMS 存储元信息的方式也不同,因此不可能有一个简单的、与数据库无关的解决方案。
不过你想要的,跳几步就可以实现。
第 1 步:定义将保存元数据信息的实体class。
@Entity
@IdClass(TableMetadataKey.class)
@Table(name = "table_metadata")
class TableMetadata {
@Column(name = "column_name")
@Id
String columnName;
@Column(name = "table_name")
@Id
String tableName;
public static class TableMetadataKey implements Serializable {
String columnName;
String tableName;
}
}
步骤 2:为实体添加存储库。
public interface TableMetadataRepository extends JpaRepository<TableMetadata, TableMetadataKey>
{
TableMetadata findByTableName(String tableName);
}
步骤 3: 定义一个名为 table_metadata
的数据库视图映射到实体 class。这必须使用特定于数据库的查询来定义(因为每个数据库都有不同的存储元数据的方式)。
可以在此步骤上执行特定于数据库的优化,例如,使用 Oracle 的实体化视图以加快访问速度等。
或者,可以使用所需的列创建名为 table_metadata
的 table,并使用 SQL 脚本定期填充。
现在应用程序可以完全访问所需的元数据。
List<TableMetadata> metadata = tableMetadataRepository.findAll()
TableMetadata metadata = tableMetadataRepository.findByTableName("myTable");
需要注意的一个问题是,并非模式中的所有 table 都可以映射为 JPA 实体,或者并非所有 table 中的所有列都可以映射为实体字段。因此,直接查询数据库元数据可能会得到与实体classes和字段不匹配的结果。
您可以使用您的实体或模型获取列名列表。我们需要的是 @Column
,它应该在你的 Entity 中使用。您将获得您在 @Column
中指定的所有详细信息。 所有的参数都是可选的,虽然最好定义所有。
@Column(name, columnDefinition, insertable, length, nullable,
precision, scale, table, unique, updatable)
我们可以通过User.class.getDeclaredFields()
(一般ModelName.class.getDeclaredFields())获取Entity中声明的所有字段。获取所有字段后,我们可以使用 field.getAnnotation(Column.class)
获取特定列,我们还可以获取 @Column
中指定的所有详细信息,如下所示
Columns: @javax.persistence.Column(nullable=false, precision=2, unique=true, name=id, length=2, scale=1, updatable=false, columnDefinition=, table=, insertable=true)
Columns: @javax.persistence.Column(nullable=true, precision=0, unique=false, name=client_id, length=255, scale=0, updatable=true, columnDefinition=, table=, insertable=true)
Columns: @javax.persistence.Column(nullable=true, precision=0, unique=false, name=firstname, length=255, scale=0, updatable=true, columnDefinition=, table=, insertable=true)
Columns: @javax.persistence.Column(nullable=true, precision=0, unique=false, name=lastname, length=255, scale=0, updatable=true, columnDefinition=, table=, insertable=true)
根据要求创建端点或方法
@GetMapping(value= "/columns/name")
public List<String> tableColumnsName()
{
List<String> Columns = new ArrayList<String>();
Field[] fields = User.class.getDeclaredFields();
for (Field field : fields) {
Column col = field.getAnnotation(Column.class);
if (col != null) {
Columns.add(col.name());
System.out.println("Columns: "+col);
}
}
return Columns;
}
Entity/Model
@Entity
@Table
public class User {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name="id")
public int id;
@Column(name="client_id")
private int clientId;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
//AllArgConstructor-Constructor
//Getters-Setters
}
通过 Postman 测试
SchemaCrawler 有一个 Java API 允许您以一般方式使用数据库元数据,而不用关心特定的数据库平台。
我想使用 spring 数据 jpa 获取所有 table 的列列表,我的数据库很灵活,所以查询应该适用于所有类型的数据库.
JPA 规范包含元模型 API,它允许您查询有关托管类型及其托管字段的信息。但是,它不涵盖底层数据库。因此,JPA 中还没有开箱即用的东西来查询数据库元数据。
每个 RDBMS 存储元信息的方式也不同,因此不可能有一个简单的、与数据库无关的解决方案。
不过你想要的,跳几步就可以实现。
第 1 步:定义将保存元数据信息的实体class。
@Entity
@IdClass(TableMetadataKey.class)
@Table(name = "table_metadata")
class TableMetadata {
@Column(name = "column_name")
@Id
String columnName;
@Column(name = "table_name")
@Id
String tableName;
public static class TableMetadataKey implements Serializable {
String columnName;
String tableName;
}
}
步骤 2:为实体添加存储库。
public interface TableMetadataRepository extends JpaRepository<TableMetadata, TableMetadataKey>
{
TableMetadata findByTableName(String tableName);
}
步骤 3: 定义一个名为 table_metadata
的数据库视图映射到实体 class。这必须使用特定于数据库的查询来定义(因为每个数据库都有不同的存储元数据的方式)。
可以在此步骤上执行特定于数据库的优化,例如,使用 Oracle 的实体化视图以加快访问速度等。
或者,可以使用所需的列创建名为 table_metadata
的 table,并使用 SQL 脚本定期填充。
现在应用程序可以完全访问所需的元数据。
List<TableMetadata> metadata = tableMetadataRepository.findAll()
TableMetadata metadata = tableMetadataRepository.findByTableName("myTable");
需要注意的一个问题是,并非模式中的所有 table 都可以映射为 JPA 实体,或者并非所有 table 中的所有列都可以映射为实体字段。因此,直接查询数据库元数据可能会得到与实体classes和字段不匹配的结果。
您可以使用您的实体或模型获取列名列表。我们需要的是 @Column
,它应该在你的 Entity 中使用。您将获得您在 @Column
中指定的所有详细信息。 所有的参数都是可选的,虽然最好定义所有。
@Column(name, columnDefinition, insertable, length, nullable, precision, scale, table, unique, updatable)
我们可以通过User.class.getDeclaredFields()
(一般ModelName.class.getDeclaredFields())获取Entity中声明的所有字段。获取所有字段后,我们可以使用 field.getAnnotation(Column.class)
获取特定列,我们还可以获取 @Column
中指定的所有详细信息,如下所示
Columns: @javax.persistence.Column(nullable=false, precision=2, unique=true, name=id, length=2, scale=1, updatable=false, columnDefinition=, table=, insertable=true)
Columns: @javax.persistence.Column(nullable=true, precision=0, unique=false, name=client_id, length=255, scale=0, updatable=true, columnDefinition=, table=, insertable=true)
Columns: @javax.persistence.Column(nullable=true, precision=0, unique=false, name=firstname, length=255, scale=0, updatable=true, columnDefinition=, table=, insertable=true)
Columns: @javax.persistence.Column(nullable=true, precision=0, unique=false, name=lastname, length=255, scale=0, updatable=true, columnDefinition=, table=, insertable=true)
根据要求创建端点或方法
@GetMapping(value= "/columns/name")
public List<String> tableColumnsName()
{
List<String> Columns = new ArrayList<String>();
Field[] fields = User.class.getDeclaredFields();
for (Field field : fields) {
Column col = field.getAnnotation(Column.class);
if (col != null) {
Columns.add(col.name());
System.out.println("Columns: "+col);
}
}
return Columns;
}
Entity/Model
@Entity
@Table
public class User {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name="id")
public int id;
@Column(name="client_id")
private int clientId;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
//AllArgConstructor-Constructor
//Getters-Setters
}
通过 Postman 测试
SchemaCrawler 有一个 Java API 允许您以一般方式使用数据库元数据,而不用关心特定的数据库平台。