经过大量的搜索和试验,我被困了......我有两个类,一个是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实例。
答案 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)
经过大量的反复试验,我终于发现错误是合法的,我确实没有足够的(即插入)权限,只有删除!!