@p-oleg

Как записать вычисляемое поле из хранимой процедуры в transient поле Entity?

Добрый день.
В базе (Firebird) есть таблица, она замаплена на Entity.
C этой таблицей работает хранимая процедура, которая возвращает как значения полей из таблицы, так и вычисляемое значение.
Под это вычисляемое значение в Entity я создал Transient переменную.
Я сделал SqlResultSetMapping, в котором написал соответствие полей из хранимой процедуры полям в Entity.
Проблема в том, что в Transient поле ничего не записывается.
Как можно победить?
Код:

@NamedStoredProcedureQuery(
        name = Building.VR,
        procedureName = "VALUATION_RESULTS_VC",
        resultSetMappings = "Mapping",
        parameters = {
            @StoredProcedureParameter(mode = ParameterMode.IN, name = "IP_ID", type = Integer.class),
            @StoredProcedureParameter(mode = ParameterMode.OUT, name = "P_ID", type = Integer.class),
            @StoredProcedureParameter(mode = ParameterMode.OUT, name = "P_CLASS", type = String.class),
            @StoredProcedureParameter(mode = ParameterMode.OUT, name = "P_CRN_VC", type = Double.class)
        }
)
@SqlResultSetMapping(
        name = "Mapping",
        entities = @EntityResult(
                entityClass = Building.class,
                fields = {
                        @FieldResult(name = "id", column = "P_ID"),
                        @FieldResult(name = "name", column = "P_CLASS"),
                        @FieldResult(name = "crn", column = "P_CRN_VC")
                }
                )
)
@Access(AccessType.FIELD)
@Entity
@Table(name = "main_tab")
public class Building extends BaseEntity {
    public static final String VR = "Asset.VR";

    @Transient <-если убрать Transient и создать такое реальное поле в таблице, то все работает. Но это поле вычисляемое и оно в таблице не нужно.
    private Double crn;

    public Double getCrn() {
        return crn;
    }

    public void setCrn(Double crn) {
        this.crn = crn;
    }
}


@MappedSuperclass
public abstract class BaseEntity {
    @Id
    @Column(name = "id")
    private Integer id;

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

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}
  • Вопрос задан
  • 243 просмотра
Пригласить эксперта
Ответы на вопрос 1
@ads83
По определению, поле с аннотацией @Transient будет игнорироваться ORM. В обе стороны: и в БД ничего не запишется, и из базы его не установить.

Но можно воспользоваться доступом на уровне методов. Помимо аннотации @Column, надо поставить на геттере аннотацию @Access(AccessType.PROPERTY).
Так как поле - вычисляемое, довольно странно видеть setCrn(Double crn) в классе. Это может смутить ORM, да и людей тоже. Я бы пошел еще дальше и переименовал getCrn так, чтобы было понятно что это вычисляемое значение.

P.S. В современных БД есть такая вещь как (materialized) view - запрос или результат работы хранимки, к результатам которого можно обращаться как к таблице. Такой подход часто используется, у него есть определенные преимущества. Наверное, тут view будет избыточным решением, но для общего развития предлагаю посмотреть и в эту сторону.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы