JPA 2.0 недостаточно прав при выполнении вставки из транзакции - PullRequest
1 голос
/ 03 января 2012

После долгих поисков и испытаний я застрял ... У меня есть два класса, один - ExpectedSecurityReturn, а другой - ForecastReturnType. ForecastReturnType является членом ExpectedSecurityReturn, но его не следует вставлять при сохранении данных. Я продолжаю получать «недостаточные привилегии», но я знаю, что у пользователя есть привилегии удаления / вставки для таблицы ожидаемой_системы безопасности, так как я тестировал с JDBC и удаление JPA работает нормально. Поэтому я думаю, что это связано с моими занятиями.

@Table(name = "EXPECTED_SECURITY_RETURNS")
@Entity
@IdClass(ExpectedSecurityReturn.ExpectedSecurityReturnPK.class)
public class ExpectedSecurityReturn {

@Id
@Column(name = "REP_SEC_ID")
private Integer repSecId;

@Id
@Column(name = "AS_OF_DATE")
private Date date;

@Id
@ManyToOne(optional = false)
@JoinColumn(name = "RETURN_TYPE_ID", referencedColumnName = "RETURN_TYPE_ID", insertable=false)
private ForecastReturnType returnType;

@Column(name="CURR_TOUSD_RET")  // local currency to usd 
private Double currencyToUsdReturn;
}

Класс первичного ключа, который включает ForecastReturnType:

    // ------------------------------
// PK
// ------------------------------
public static class ExpectedSecurityReturnPK implements Serializable {

    private static final long serialVersionUID = 1325372032981567439L;

    public ExpectedSecurityReturnPK() {
    }

    public ExpectedSecurityReturnPK(final Integer repSecId,
            final Date asOfDate, ForecastReturnType returnType) {
        if (repSecId == null)
            throw new IllegalArgumentException("null rep sec id");
        if (asOfDate == null)
            throw new IllegalArgumentException("null asOfDate");
        if (returnType == null)
            throw new IllegalArgumentException("null returnType");

        this.repSecId = repSecId;
        this.date = new Date(asOfDate.getTime());
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        final ExpectedSecurityReturnPK that = (ExpectedSecurityReturnPK) o;

        if (repSecId != that.repSecId)
            return false;
        if (!date.equals(that.date))
            return false;
        if (!returnType.equals(that.returnType))
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = repSecId;
        result = 31 * result + date.hashCode();
        result = 31 * result + returnType.getForecastTypeId();
        return result;
    }

    private int repSecId;
    private Date date;
    private ForecastReturnType returnType;
}

и ForecastReturnType:

@Table(name="EXPECTED_SEC_RET_TYPE_DECODE")
@Entity
public class ForecastReturnType {

@Id
@Column(name="RETURN_TYPE_ID")
private int forecastTypeId;

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

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

@OneToMany(fetch=FetchType.LAZY, mappedBy="returnType")
Collection<ExpectedSecurityReturn> expectedSecurityReturns;
}

Может ли кто-нибудь помочь мне понять, что я делаю неправильно? Я пробовал многие вещи без успеха ... Я думаю, что виновником является ExpectedSecurityReturn.returnType, так как я знаю, что пользователь не имеет привилегий.

По сути, мне нужно вставить / сохранить экземпляры ExpectedSecurityReturn.

Ответы [ 3 ]

0 голосов
/ 03 января 2012

Я согласен с PlexQ, что производные идентификаторы и составные ключи - довольно сложные части JPA.

Однако в спецификации JPA 2.0 содержится хороший набор примеров, иллюстрирующих эти темы, и эти примеры в основном работают в разных реализациях JPA.

Для вашей спецификации случая предлагается вставить в @IdClassполе с именем @ManyToOne поле и тип @Id поле ссылочной сущности:

@Entity
public class Employee {
    @Id long empId;
    String empName;
    ...
}

public class DependentId {
    String name; // matches name of @Id attribute
    long emp; // matches name of @Id attribute and type of Employee PK
}

@Entity
@IdClass(DependentId.class)
public class Dependent {
    @Id String name;
    // id attribute mapped by join column default
    @Id @ManyToOne Employee emp;
    ...

}

См. также:

0 голосов
/ 18 января 2012

После долгих проб и ошибок я, наконец, понял, что ошибка допустима, и у меня действительно не было достаточных (то есть, вставок) привилегий, только удалить !!

0 голосов
/ 03 января 2012

Ну, есть пара вещей.

Я бы настоятельно не рекомендовал даже пытаться сделать это.Вы можете потратить впустую свою жизнь, разбираясь с аннотациями JPA и такими странными проблемами, которые, кажется, никогда не работают правильно.Вы также обнаружите, что разные JPA-провайдеры будут вести себя немного по-разному, когда речь идет о более сложных структурах, подобных этой, и это вдвойне выгодно для наследования.

Вам действительно намного лучше создать уникальный ключ для EXPECTED_SECURITY_RETURNSи просто живя с этим, это сделает вашу жизнь на Java намного проще.

Если у вас есть , чтобы сделать что-то подобное, я не удивлен, что JPA противится первичномуключевым компонентом будет другой объект объекта.Хотя это, конечно, вполне возможно в СУБД, но, по-видимому, такие мелочи могут сбить JPA.определение постоянства для большинства поставщиков JPA, конечно же, Ecpliselink и Hibernate).Я был бы готов поспорить, что он пытается запустить обновление EXPECTED_SEC_RET_TYPE_DECODE, и если нет, он может пытаться получить блокировку (таблицу, строку или другое в зависимости от вашей СУБД).Если у пользователя нет разрешения ни на выполнение блокировки, ни на обновление этой таблицы, в зависимости от точной реализации, запрос может завершиться ошибкой с разрешениями.

Для JPA целесообразно удерживать запросблокировка этой таблицы, поскольку существует вероятность того, что во время транзакции запись, на которую ссылается EXPECTED_SEC_RET_TYPE_DECODE, может измениться, поэтому она должна гарантировать, что она не будет обновляться / вставляться в другую таблицу.Последнее, что я проверил, нет никакого способа сказать JPA, что эта таблица по существу статична.Если вы используете Hibernate, вы можете попробовать аннотацию @ReadOnly, но в прошлом мало что я пробовал, чтобы обойти такие вещи.

Если вы найдете лучшее решение, не стесняйтесьопубликуйте это так, чтобы остальные могли учиться !!

...