-1

I am trying to attach image files to an entity called product. I can create a product along with the image pretty well but when i try to delete an image i get the following error.

HTTP 500 - Request processing failed; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.IJM.model.Product

Product Class

@Entity
@Table(name = "Product")
public class Product {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private Long id;

@NotNull
@Size(min = 3, max = 10)
@Column(name = "Code", nullable = false)
private String code;

@NotNull
@Size(min = 3, max = 50)
@Column(name = "Name", nullable = false)
private String name;

@Size( max = 50)
@Column(name = "Description", nullable = false)
private String description;

@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "Id_Category")
private Category category;

@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "Id_Unit")
private Unit unit;

@OneToMany(cascade = CascadeType.ALL,
        fetch= FetchType.EAGER,
        orphanRemoval = true,
        mappedBy="product")
private Set<Image> images;

public String getCode() {
    return code;
}

public void setCode(String code) {
    this.code = code;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}
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 Category getCategory() {
    return category;
}

public void setCategory(Category category) {
    if(this.category==null||!this.category.equals(category))
    {
        this.category=category;
    }
    return;
}

public Unit getUnit() {
    return unit;
}

public void setUnit(Unit unit) {
    if(this.unit==null||!this.unit.equals(unit))
    {
        this.unit=unit;
    }
    return;
}

public Set<Image> getImages() {
    return images;
}

public void setImages(Set<Image> images) {
    this.images = images;
}
}

Image Class

@Entity
@Table(name = "product_Image")
public class Image {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id", nullable = false)
private long id;

@Lob
@Column(name = "File", nullable = false)
private byte[] file;

@Column(name = "Checksum",nullable = false)
private String checksum;

@Column(name = "Extension",nullable = false)
private String extension;

@Column(name = "File_Name",nullable = false)
private String file_name;

@Column(name = "Size",nullable = false)
private int size;

@Column(name = "Last_Updated",nullable = false)
private Timestamp last_Updated;


@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="Id_Product")
private Product product;

@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name="Id_Directory")
private Directory directory;

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public byte[] getFile() {
    return file;
}

public void setFile(byte[] file) {
    this.file = file;
}

public String getChecksum() {
    return checksum;
}

public void setChecksum(String checksum) {
    this.checksum = checksum;
}

public String getExtension() {
    return extension;
}

public void setExtension(String extension) {
    this.extension = extension;
}

public String getFile_name() {
    return file_name;
}

public void setFile_name(String file_name) {
    this.file_name = file_name;
}

public int getSize() {
    return size;
}

public void setSize(int size) {
    this.size = size;
}

public Timestamp getLast_Updated() {
    return last_Updated;
}

public void setLast_Updated(Timestamp last_Updated) {
    this.last_Updated = last_Updated;
}

public Product getProduct() {
    return product;
}

public void setProduct(Product product) {
    this.product = product;
}

public Directory getDirectory() {
    return directory;
}

public void setDirectory(Directory directory) {
    this.directory = directory;
}   

And this is the code for the controller calling the deleting method

@RestController
@RequestMapping("/image")
public class ImageController {

@Autowired
ProductService productService;

@Autowired
ImageService imageService;

private static final String productImagePath="C:\\IJM\\Images\\Product\\";

@RequestMapping(value = "/product/{code}", method = RequestMethod.DELETE)
public ResponseEntity<Image> deleteProductImage(@PathVariable("code") String code) {
    System.out.println("Fetching & Deleting Image for product " + code);
    code = code.toUpperCase();

    if (!productService.isProductExist(code)) {
        System.out.println("Product with code " + code + " not found");
        return new ResponseEntity<Image>(HttpStatus.NOT_FOUND);
    }
    else
    {
        Product product = productService.findProductByCode(code);
        if(product.getImages()!=null)
        {
            for(Image image:product.getImages())
            {
                product.getImages().remove(image);
                image.setProduct(null);
                imageService.deleteImage(image.getId());
            }
            productService.saveProduct(product);
            try{

                File file = new File(productImagePath+code);

                if(FileDeleter.removeDirectory(file)){
                    System.out.println(file.getName() + " is deleted!");
                }else{
                    System.out.println("Delete operation is failed.");
                }

            }catch(Exception e){

                e.printStackTrace();

            }
        }
    }

    return new ResponseEntity<Image>(HttpStatus.NO_CONTENT);
}
}

In case someone else is wondering.. the service just calls the DAO

    @Override
public void deleteImage(long id) {
    Image image = imageDao.findById(id);
    imageDao.delete(image);

}

This is the Dao Class

@Repository("imageDao")
public class ImageDaoImpl extends AbstractDao<Long,Image> implements ImageDao{


@Override
public void delete(Image image) {
    super.delete(image);

}
}

This is the code in my abstract DAO class

public void delete(T entity) {
    getSession().delete(entity);
}

1 Answers1

0

It seems these line are not in proper order.

product.getImages().remove(image);
image.setProduct(null);
imageService.deleteImage(image.getId());

Also not sure what imageService.deleteImage(image.getId()); is doing. It is not required.

Please try like below.

for(Image image:product.getImages())
   {
    image.setProduct(null);
    product.getImages().remove(image);
   }
productService.saveProduct(product);

This should be enough. I know it doesn't make any sense to change the order but It had worked for me.

Vijendra Kumar Kulhade
  • 2,217
  • 3
  • 15
  • 25
  • :c it appers it didnt make a difference in my code.. I posted more of it in case i get something wrong. – user3676579 May 30 '16 at 20:06
  • Did you try removing deleteImage call. The error you are getting is due to Image entity you have already removed also saveProduct implementation should be saveOrUpdate(product) in case of hibernate or merge(product) in case of JPA. – Vijendra Kumar Kulhade May 30 '16 at 20:20
  • Lol.. yeah it needed to be an update..that was it, Im sorry, I think that was dumb from my part! thank you so much for your time and knowledge! – user3676579 May 30 '16 at 20:34