Here is my code. Subscriber has a list of DeviceLine. DeviceLine has ref to actual Device. SubscriberService is business logic layer to save subscribers. Please let me know where the problem could be. We tried merge() in modifySubscriber() but still the same problem.
Code:
package com.mycomany.test;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "subscriber")
public class Subscriber {
/**
* Internal database id.
*/
@Id
@Column(name = "id", nullable = false)
protected Long id;
protected String resourceId;
protected String name;
@OneToMany (cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.LAZY
)
@JoinColumn (name = "subscriber_id")
@org.hibernate.annotations.Cascade({
org.hibernate.annotations.CascadeType.DELETE_ORPHAN,
org.hibernate.annotations.CascadeType.SAVE_UPDATE
})
private Set<DeviceLine> listOfDevices;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<DeviceLine> getListOfDevices() {
return listOfDevices;
}
public void setListOfDevices(Set<DeviceLine> listOfDevices) {
this.listOfDevices = listOfDevices;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getResourceId() {
return resourceId;
}
public void setResourceId(String resourceId) {
this.resourceId = resourceId;
}
}//end class
Code:
package com.mycomany.test;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "device_line")
public class DeviceLine {
/**
* Internal database id.
*/
@Id
@Column(name = "id", nullable = false)
protected Long id;
protected String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "device_id")
@org.hibernate.annotations.Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE })
private Device device;
public boolean equals(Object o) {
DeviceLine d = (DeviceLine)o;
if(this.getDevice().getResourceId().equals(d.getDevice().getResourceId())
&& this.getName().equals(dl.getName())) {
return true;
}
return false;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Code:
package com.mycomany.test;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "device")
public class Device {
/**
* Internal database id.
*/
@Id
@Column(name = "id", nullable = false)
protected Long id;
protected String name;
protected String resourceId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getResourceId() {
return resourceId;
}
public void setResourceId(String resourceId) {
this.resourceId = resourceId;
}
}
Code:
package com.mycomany.test;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import vzbi.cssop.common.util.Util;
public final class SubscriberService {
@Transactional(propagation=Propagation.REQUIRED)
public void createSubscriber(Subscriber subscriber) {
Subscriber sub = null;
Device dev = null;
try {
Set<DeviceLine> device_lines = subscriber.getListOfDevices();
for (DeviceLine d : device_lines) {
dev = daoManager.getDeviceDao().getByResourceId(d.getDevice().getResourceId());
if(dev != null) {
d.setDevice(dev);
}
}
daoManager.getSubscriberDao().save(subscriber);
} catch (Throwable e) {
} finally {
}
return;
}
@Transactional(propagation=Propagation.REQUIRED)
public void modifySubscriber(Subscriber subscriber) {
Subscriber sub = null;
try {
//load sub from database
sub = daoManager.getSubscriberDao().getByResourceId(subscriber.getResourceId());
if (sub == null) {
throw new RuntimeException("Subscriber not found!");
}
sub.setName(subscriber.getName());
Set<DeviceLine> device_lines = subscriber.getListOfDevices();
for (DeviceLine d : device_lines) {
if(d.getDevice().getId() == null ) {
Device dev = daoManager.getDeviceDao().getByResourceId(d.getDevice().getResourceId());
if(dev != null) {
d.setDevice(dev);
}
}
}
updateSet(sub.getListOfDevices(), subscriber.getListOfDevices());
daoManager.getSubscriberDao().save(sub);
} catch (Throwable e) {
} finally {
}
return;
}
public static <T> void updateSet(Set<T> currentSet, Set<T> newSet) {
Iterator<T> it = currentSet.iterator();
while(it.hasNext()) {
if(!newSet.contains(it.next())) {
it.remove();
}
}
for (T t : newSet) {
if(!currentSet.contains(t)) {
currentSet.add(t);
}
}
}//end updateSet()
}//end class
Thanks
Ramin