Java 使用JPA1.0注释派生的复合键(复合键多对一)
我有一个简单的关系,如上图所示 我可以使用以下Hibernate映射来保持这一点:Java 使用JPA1.0注释派生的复合键(复合键多对一),java,hibernate,jpa,annotations,Java,Hibernate,Jpa,Annotations,我有一个简单的关系,如上图所示 我可以使用以下Hibernate映射来保持这一点: <class name="Strategy" table="Strategy"> <id name="id" column="StrategyId" unsaved-value="any"> <generator class="identity"/> </id> <property name="status" colum
<class name="Strategy" table="Strategy">
<id name="id" column="StrategyId" unsaved-value="any">
<generator class="identity"/>
</id>
<property name="status" column="Status"/>
</class>
<class name="Alert" table="Alert">
<id name="id" column="AlertId">
<generator class="identity"/>
</id>
<property name="name" column="Name"/>
</class>
<class name="StrategyAlert" table="StrategyAlert">
<composite-id>
<key-many-to-one name="strategy" class="Strategy" column="StrategyId"/>
<key-many-to-one name="alert" class="Alert" column="AlertId"/>
</composite-id>
<property name="nominal" column="Nominal"/>
</class>
策略类:
@Entity
@Table(name="STRATEGY")
public class Strategy implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="STRATEGYID")
private int id;
@Column(name="STATUS")
private String status;
}
StrategyAlertPK类:
public class StrategyAlertPK implements Serializable {
private int strategyId;
private int alertId;
}
StrategyAlert类:
@Entity
@Table(name="STRATEGYALERT")
@IdClass(StrategyAlertPK.class)
public class StrategyAlert implements Serializable {
@Id
@Column(name="STRATEGYID")
private int strategyId;
@Id
@Column(name="ALERTID")
private int alertId;
@ManyToOne
@JoinColumn(name="STRATEGYID", insertable=false, updatable=false)
private Strategy strategy;
@ManyToOne
@JoinColumn(name="ALERTID", insertable=false, updatable=false)
private Alert alert;
@Column
private String nominal;
}
测试用例:
em.getTransaction().begin();
Alert alert = new Alert();
alert.setName("NAME");
em.persist(alert);
Strategy strategy = new Strategy();
strategy.setStatus("STATUS");
em.persist(strategy);
StrategyAlert strategyAlert = new StrategyAlert();
strategyAlert.setAlert(alert);
strategyAlert.setStrategy(strategy);
strategyAlert.setNominal("NOMINAL");
em.persist(strategyAlert);
em.getTransaction().commit();
我得到以下错误:
引用完整性约束冲突:“FK80432DA9CE00672E:PUBLIC.STRATEGYALERT外键(STRATEGYID)引用PUBLIC.STRATEGY(STRATEGYID)(0)
我正在使用
生成表
如何正确注释StrategyAlert类?查看以下问题: 我认为这里的问题是您必须加入JPA1中描述的Id声明和多通声明,我现在无法测试代码,但或多或少它必须是这样
@Entity
@Table(name="STRATEGYALERT")
@IdClass(StrategyAlertPK.class)
public class StrategyAlert implements Serializable {
@Id
@ManyToOne
@JoinColumn(name="STRATEGYID", insertable=false, updatable=false)
private Strategy strategy;
@Id
@ManyToOne
@JoinColumn(name="ALERTID", insertable=false, updatable=false)
private Alert alert;
@Column
private String nominal;
// TODO Getters and setters
}
更新
嗨
现在我可以测试代码了,正在为m编写以下代码(一些修正):
策略
/**
*
*/
package hib;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="STRATEGY")
public class Strategy implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="STRATEGYID")
private int id;
@Column(name="STATUS")
private String status;
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the status
*/
public String getStatus() {
return status;
}
/**
* @param status the status to set
*/
public void setStatus(String status) {
this.status = status;
}
}
战略警报PK
/**
*
*/
package hib;
import java.io.Serializable;
import javax.persistence.Embeddable;
/**
*
*/
@Embeddable
public class StrategyAlertPK implements Serializable {
@ManyToOne
private Strategy strategy;
@ManyToOne
private Alert alert;
/**
* @return the strategy
*/
public Strategy getStrategy() {
return strategy;
}
/**
* @param strategy the strategy to set
*/
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
/**
* @return the alert
*/
public Alert getAlert() {
return alert;
}
/**
* @param alert the alert to set
*/
public void setAlert(Alert alert) {
this.alert = alert;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
StrategyAlertPK that = (StrategyAlertPK) o;
if (strategy != null ? !strategy.equals(that.strategy) : that.strategy != null) {
return false;
}
if (alert != null ? !alert.equals(that.alert) : that.alert != null) {
return false;
}
return true;
}
public int hashCode() {
int result;
result = (strategy != null ? strategy.hashCode() : 0);
result = 31 * result + (alert != null ? alert.hashCode() : 0);
return result;
}
}
战略警报
/**
*
*/
package hib;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="STRATEGYALERT")
@AssociationOverrides({ @AssociationOverride(name = "pk.strategy", joinColumns = @JoinColumn(name = "STRATEGYID")),
@AssociationOverride(name = "pk.alert", joinColumns = @JoinColumn(name = "ALERTID")) })
public class StrategyAlert implements Serializable {
@EmbeddedId
private StrategyAlertPK pk = new StrategyAlertPK();
@Column
private String nominal;
@Transient
public Strategy getStrategy() {
return pk.getStrategy();
}
public void setStrategy(Strategy strategy) {
pk.setStrategy(strategy);
}
@Transient
public Alert getAlert() {
return pk.getAlert();
}
public void setAlert(Alert alert) {
pk.setAlert(alert);
}
/**
* @return the nominal
*/
public String getNominal() {
return nominal;
}
/**
* @param nominal the nominal to set
*/
public void setNominal(String nominal) {
this.nominal = nominal;
}
}
有了这些代码,您的测试运行正常(我用JPA1.0.1、Hibernate 3.3.1.GA和spring 2.5.5对其进行了测试)。我使用H2作为内存数据库,所以我必须在生成的值中将标识更改为自动,也许您不需要这样做
希望有帮助!我已经找到了解决办法,但我认为这不是正确的方法 我有一个用于ID的静态嵌套类。然后在两个setter方法中我也设置了ID。这似乎是一种非常手动的方法,肯定有更好的方法吗
@Entity
@Table(name="STRATEGYALERT")
public class StrategyAlert {
@Embeddable
public static class Id implements Serializable {
private static final long serialVersionUID = -8270591004786497335L;
@Column(name="STRATEGYID")
private int strategyId;
@Column(name="ALERTID")
private int alertId;
public Id() {}
public Id(int strategyId, int alertId) {
this.strategyId = strategyId;
this.alertId = alertId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + alertId;
result = prime * result + strategyId;
return result;
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Id other = (Id)obj;
if(alertId != other.alertId)
return false;
if(strategyId != other.strategyId)
return false;
return true;
}
}
@EmbeddedId
private Id id = new Id();
@ManyToOne
@JoinColumn(name="STRATEGYID", insertable=false, updatable=false)
private Strategy strategy;
@ManyToOne
@JoinColumn(name="ALERTID", insertable=false, updatable=false)
private Alert alert;
@Column(name="NOMINAL")
private String nominal;
public StrategyAlert() {}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
// SET ID
this.id.strategyId = strategy.getId();
}
public void setAlert(Alert alert) {
this.alert = alert;
// SET ID
this.id.alertId = alert.getId();
}
// Other Getters & Setters...
}
感谢Francisco的帮助,我尝试了这一点,但我得到了一个Id类找不到其属性的错误:“在用@IdClass:hib.StrategyAlert注释的实体中找不到属性(alertId,strategyId)“我已经尝试了我能想到的一切,但我无法让它发挥作用。考虑到它在XML中的易用性,您会认为使用注释应该足够容易。有人知道如何让这个工作吗?嗨,我更新了我的答案,现在我可以测试代码了,正在为我工作。希望有帮助我也在使用H2。我复制/粘贴了您刚刚重命名为hib的代码包。我收到以下错误:
原因:org.hibernate.PropertyAccessException:无法通过hib.StrategyAlertPK.alert的反射设置器设置字段值
和原因:java.lang.IllegalArgumentException:无法将int字段hib.StrategyAlertPK.alert设置为hib.alert
。我正在使用HIbernate v3.2.4,我可能会尝试另一个版本,因为我看不出为什么会发生这种情况。我用最新版本的HIbernate进行了尝试,我可以使用-v3.3.1.GA/Annotations 3.4.0.GA/EntityManager 3.4.0.GA,我得到了完全相同的错误:无法将int field hib.StrategyAlertPK.alert设置为hib.alert
。我不知道下一步该怎么办
/**
*
*/
package hib;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="STRATEGYALERT")
@AssociationOverrides({ @AssociationOverride(name = "pk.strategy", joinColumns = @JoinColumn(name = "STRATEGYID")),
@AssociationOverride(name = "pk.alert", joinColumns = @JoinColumn(name = "ALERTID")) })
public class StrategyAlert implements Serializable {
@EmbeddedId
private StrategyAlertPK pk = new StrategyAlertPK();
@Column
private String nominal;
@Transient
public Strategy getStrategy() {
return pk.getStrategy();
}
public void setStrategy(Strategy strategy) {
pk.setStrategy(strategy);
}
@Transient
public Alert getAlert() {
return pk.getAlert();
}
public void setAlert(Alert alert) {
pk.setAlert(alert);
}
/**
* @return the nominal
*/
public String getNominal() {
return nominal;
}
/**
* @param nominal the nominal to set
*/
public void setNominal(String nominal) {
this.nominal = nominal;
}
}
@Entity
@Table(name="STRATEGYALERT")
public class StrategyAlert {
@Embeddable
public static class Id implements Serializable {
private static final long serialVersionUID = -8270591004786497335L;
@Column(name="STRATEGYID")
private int strategyId;
@Column(name="ALERTID")
private int alertId;
public Id() {}
public Id(int strategyId, int alertId) {
this.strategyId = strategyId;
this.alertId = alertId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + alertId;
result = prime * result + strategyId;
return result;
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Id other = (Id)obj;
if(alertId != other.alertId)
return false;
if(strategyId != other.strategyId)
return false;
return true;
}
}
@EmbeddedId
private Id id = new Id();
@ManyToOne
@JoinColumn(name="STRATEGYID", insertable=false, updatable=false)
private Strategy strategy;
@ManyToOne
@JoinColumn(name="ALERTID", insertable=false, updatable=false)
private Alert alert;
@Column(name="NOMINAL")
private String nominal;
public StrategyAlert() {}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
// SET ID
this.id.strategyId = strategy.getId();
}
public void setAlert(Alert alert) {
this.alert = alert;
// SET ID
this.id.alertId = alert.getId();
}
// Other Getters & Setters...
}