@OneToMany @ManyToOne with composite
mtorrens Jun 21, 2006 6:46 AMI have a natural @ManyToMany relationship between Service and Deployment objects. Service objects have many Deployments. Deployment objects can be used by many Services. However, I haven't use a @ManyToMany because the relationship between the two objects has extra attributes, so I use an association table (ServiceDeployment).
The ServiceDeployment table has a composite key made from both serviceid and deploymentid.
When the ServiceDeployment table contains data about a Service, I can't delete the Service object. I get "Cannot delete or update a parent row: a foreign key constraint fails"
I think I need a JoinTable annotation on the @OneToMany and @ManyToOne relationships between Service and ServiceDeployment but I can't get the syntax right. Can someone please suggest the syntax for the @JoinTable annotation when a composite key is used.
Thanks in advance.
Three tables
CREATE TABLE `service` ( `serviceid` bigint(20) NOT NULL auto_increment, `name` varchar(255) NOT NULL default '', `version` bigint(20) default NULL, `description` varchar(255) default NULL, PRIMARY KEY (`serviceid`) ) CREATE TABLE `deployment` ( `deploymentid` bigint(20) NOT NULL auto_increment, `name` varchar(255) NOT NULL default '', `version` bigint(20) default NULL, PRIMARY KEY (`deploymentid`) ) CREATE TABLE `servicedeployment` ( `deploymentid` bigint(20) NOT NULL default '0', `serviceid` bigint(20) NOT NULL default '0', `pre` tinyint(1) default NULL, `post` tinyint(1) default NULL, PRIMARY KEY (`deploymentid`,`serviceid`), KEY `FK5A11633AE720A8AF` (`deploymentid`), KEY `FK5A11633A2157D23B` (`serviceid`), CONSTRAINT `FK5A11633A2157D23B` FOREIGN KEY (`serviceid`) REFERENCES `service` (`serviceid`), CONSTRAINT `FK5A11633AE720A8AF` FOREIGN KEY (`deploymentid`) REFERENCES `deployment` (`deploymentid`) )
ServiceDeploymentPK Class
@Embeddable public class ServiceDeploymentPK implements Serializable { /* the pk fields */ private Long serviceId; private Long deploymentId; @Column( name = "serviceid" ) public Long getServiceId() { return this.serviceId; } public void setServiceId( Long serviceId ) { this.serviceId = serviceId; } @Column( name = "deploymentid" ) public Long getDeploymentId() { return this.deploymentId; } public void setDeploymentId( Long deploymentId ) { this.deploymentId = deploymentId; } ...
ServiceDeployment Class
@Entity @Table(name = "servicedeployment") public class ServiceDeployment implements Serializable { private static final long serialVersionUID = 589798996756500911L; private ServiceDeploymentPK key; private Boolean pre; private Boolean post; private Service service; private Deployment deployment; public ServiceDeployment() { } @EmbeddedId public ServiceDeploymentPK getKey() { return this.key; } public void setKey( ServiceDeploymentPK key ) { this.key = key; } public Boolean getPre() { return pre; } public void setPre( Boolean pre ) { this.pre = pre; } public Boolean getPost() { return post; } public void setPost( Boolean post ) { this.post = post; } @ManyToOne @JoinColumn(name = "serviceid", referencedColumnName = "serviceid", insertable = false, updatable = false) public Service getService() { return service; } public void setService( Service service ) { this.service = service; } @ManyToOne @JoinColumn(name = "deploymentid", referencedColumnName = "deploymentid", insertable = false, updatable = false) public Deployment getDeployment() { return deployment; } public void setDeployment( Deployment deployment ) { this.deployment = deployment; } }
Service Class
@Entity @Table( name = "service" ) public class Service implements Serializable { private static final long serialVersionUID = -5735355220126370351L; // Properties private Long serviceId; private Long version; private String name; private String description; // One to Many private Set<ServiceDeployment> serviceDeployments; public Service() { } @Id(generate = GeneratorType.AUTO) @Column( name="serviceid" ) public Long getServiceId() { return serviceId; } public void setServiceId( Long serviceId ) { this.serviceId = serviceId; } @Version public Long getVersion() { return version; } public void setVersion( Long version ) { this.version = version; } @Column( nullable=false ) public String getName() { return name; } public void setName( String name ) { this.name = name; } @OneToMany ( mappedBy="service", cascade=CascadeType.ALL, fetch=FetchType.EAGER ) @org.hibernate.annotations.Cascade( value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN ) public Set<ServiceDeployment> getServiceDeployments() { return serviceDeployments; } public void setServiceDeployments( Set<ServiceDeployment> serviceDeployments ) { this.serviceDeployments = serviceDeployments; } }
Deployment Class
@Entity @Table( name = "deployment" ) public class Deployment implements Serializable { private static final long serialVersionUID = -7754844521569522001L; // Properties private Long deploymentId; private Long version; private String name; // Children private Set<ContextVariable> contextVariables; // One to Many private Set<ServiceDeployment> serviceDeployments; public Deployment() { } @Id(generate = GeneratorType.AUTO) @Column( name="deploymentid" ) public Long getDeploymentId() { return deploymentId; } public void setDeploymentId( Long deploymentId ) { this.deploymentId = deploymentId; } @Version public Long getVersion() { return version; } public void setVersion( Long version ) { this.version = version; } @Column( unique=true, length=255, nullable=false ) public String getName() { return name; } public void setName( String name ) { this.name = name; } @OneToMany( mappedBy="deployment", cascade=CascadeType.ALL, fetch=FetchType.EAGER ) @org.hibernate.annotations.Cascade( value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN ) @OrderBy("name ASC") public Set<ContextVariable> getContextVariables() { return contextVariables; } public void setContextVariables( Set<ContextVariable> contextVariables ) { this.contextVariables = contextVariables; } @OneToMany( mappedBy="deployment", cascade=CascadeType.ALL ) public Set<ServiceDeployment> getServiceDeployments() { return serviceDeployments; } public void setServiceDeployments( Set<ServiceDeployment> serviceDeployments ) { this.serviceDeployments = serviceDeployments; } }