Есть ли какой-нибудь самый простой способ получить метаданные таблицы (список имен столбцов) в Spring Data JPA? который я мог бы использовать в универсальной базе данных
Я нахожусь в ситуации, когда я хочу получить список всех столбцов таблицы, используя данные весны jpa, моя база данных является гибкой, поэтому запрос должен работать для всех типов баз данных.
4 ответа
Спецификация JPA содержит API-интерфейс метамодели, который позволяет запрашивать информацию об управляемых типах и их управляемых полях. Это, однако, не распространяется на базовую базу данных. Таким образом, в JPA пока нет ничего нестандартного для запроса метаданных базы данных.
Способ хранения метаданных в каждой СУБД также отличается, поэтому не может быть простого решения, не зависящего от базы данных.
Однако то, что вы хотите, может быть достигнуто с помощью нескольких прыжков.
Шаг 1: Определите класс сущности, который будет содержать информацию метаданных.
@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
быть сопоставленным с классом сущности. Это должно быть определено с использованием запроса к базе данных (поскольку каждая база данных имеет свой способ хранения своих метаданных).
На этом этапе можно выполнить оптимизацию для конкретной базы данных, например, с использованием материализованных представлений в Oracle для более быстрого доступа и т. Д.
Кроме того, таблица с именем table_metadata
может быть создан с необходимыми столбцами и периодически заполняться с помощью сценария SQL.
Теперь приложение имеет полный доступ к необходимым метаданным.
List<TableMetadata> metadata = tableMetadataRepository.findAll()
TableMetadata metadata = tableMetadataRepository.findByTableName("myTable");
Следует отметить одну проблему, заключающуюся в том, что не все таблицы в схеме могут быть отображены как объекты JPA, или не все столбцы во всех таблицах могут быть отображены как поля объектов. Поэтому прямой запрос метаданных базы данных может дать результаты, которые не соответствуют классам и полям сущности.
Вы можете получить список имен столбцов, используя свою сущность или модель. Нам нужно@Column
, который следует использовать в вашем Entity. Вы получите все данные, указанные в@Column
. Все параметры являются необязательными, хотя все можно определить.
@Column(имя, определение столбца, вставляемый, длина, допускающий значение NULL, точность, масштаб, таблица, уникальный, обновляемый)
Мы можем получить все поля, объявленные в Entity, с помощью User.class.getDeclaredFields()
(обычно ModelName.class.getDeclaredFields()). После получения всех данных мы можем получить конкретный столбец, используя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
@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
}
SchemaCrawler имеет Java API, который позволяет вам работать с метаданными базы данных в общем виде, то есть, не заботясь о конкретной платформе базы данных.
Приведенное выше решение работает для «простого первичного ключа». Но для «составного первичного ключа» решение указано ниже.
BuidingKey --> Составной первичный ключ
@GetMapping("/columns")
public List<String> getColumns() {
List<String> entityColumns = Arrays.asList(Building.class.getDeclaredFields()).stream().map(Field::getName)
.collect(Collectors.toList());
List<String> entityCompositePKColumns = Arrays.asList(BuidingKey.class.getDeclaredFields()).stream().map(Field::getName)
.collect(Collectors.toList());
entityCompositePKColumns.addAll(entityColumns);
return entityCompositePKColumns;
}