从事务执行插入时,JPA 2.0权限不足

时间:2012-01-03 16:15:32

标签: java jpa insert persistence jpa-2.0

经过大量的搜索和试验,我被困了......我有两个类,一个是ExpectedSecurityReturn,另一个是ForecastReturnType。 ForecastReturnType是ExpectedSecurityReturn的成员,但在保留数据时不应插入。我一直得到“权限不足”但我知道用户确实拥有对表expected_security_return的删除/插入权限,因为我使用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 :(得分:0)

嗯,有几件事。

我甚至不建议尝试这样做。你可以浪费你的生命来搞清楚JPA注释和这样的奇怪问题,这些问题似乎从来没有像现在这样正常。您还会发现,当涉及到更复杂的结构时,不同的JPA提供程序的行为会略有不同,并且继承会加倍。

你最好在EXPECTED_SECURITY_RETURNS上创建一个独特的密钥,只要与它一起生活,它将使你的Java生活变得更加容易。

如果你做这样的事情,我并不感到惊讶,JPA不愿意让主键组件成为另一个实体对象。虽然这在RDBMS当然很有可能,但看起来像这样的小东西会让JPA绊倒。

我还会检查你的JPA impl将会发布的查询日志(在大多数JPA提供程序的持久性定义中,它可以很容易地配置,当然还有Ecpliselink和Hibernate)。我愿意打赌它试图在EXPECTED_SEC_RET_TYPE_DECODE上运行更新,如果没有,它可能会尝试获取锁(表,行或其他取决于您的DBMS)。如果用户没有权限对该表执行锁定或更新,则根据具体实现,查询可能会因权限问题而失败。

JPA想要对该表进行锁定是合理的,因为在事务期间,EXPECTED_SEC_RET_TYPE_DECODE中引用的条目可能会被更改,因此必须确保它在更新时不会/插入另一张桌子上。最后我检查过,没有办法告诉JPA这个表基本上是静态的。如果你正在使用Hibernate,你可以试试@ReadOnly注释,但在过去,我尝试的并不多,可以解决这个问题。

如果您确实找到了更好的解决方案,请随意发布,以便我们其他人可以学习!!

答案 1 :(得分:0)

我同意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;
    ...

}

另见:

答案 2 :(得分:0)

经过大量的反复试验,我终于发现错误是合法的,我确实没有足够的(即插入)权限,只有删除!!