Domanda

I have some trouble with Hibernate 4 and inheritance:

I use a ChildData class which inherit from BaseData by a JOIN inheritance strategy. My mapping is done by annotation in classes.

Everything is working fine except that when I delete a ChildData instance (with session.delete() or with a Hql query) the BaseData entry is also deleted.

I understand that in most case this is the awaited behavior, but for my particular case, I would like to preserve the BaseData entry no matter what for history purpose.

In other words I want all actions on the child class to be cascaded to base class except deletion.

I have already tried @OnCascade on the child class, with no success.

Is it a way to achieve this by code or do I have to use a SQL Trigger ON DELETE ?

EDIT : Base Class

@Entity
@Table(name = "dbBenchHistory", uniqueConstraints = @UniqueConstraint(columnNames = "Name"))
@Inheritance(strategy = InheritanceType.JOINED )
public class DbBenchHistory implements java.io.Serializable {

private int id;
private String name;
private String computer;
private String eap;
private Date lastConnexion;
private Set<DbPlugin> dbPlugins = new HashSet<DbPlugin>(0);
private Set<DbSequenceResult> dbSequenceResults = new HashSet<DbSequenceResult>(
        0);

public DbBenchHistory() {
}

public DbBenchHistory(int id, String name) {
    this.id = id;
    this.name = name;
}

public DbBenchHistory(int id, String name, String computer, String eap,
        Date lastConnexion, Set<DbPlugin> dbPlugins,
        Set<DbSequenceResult> dbSequenceResults) {
    this.id = id;
    this.name = name;
    this.computer = computer;
    this.eap = eap;
    this.lastConnexion = lastConnexion;
    this.dbPlugins = dbPlugins;
    this.dbSequenceResults = dbSequenceResults;
    }


@Id
@Column(name = "Id", unique = true, nullable = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
public int getId() {
    return this.id;
}

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

//Getters/Setters

Child Class :

@Entity
@Table(name = "dbBench")
@OnDelete(action=OnDeleteAction.NO_ACTION)
public class DbBench extends DbBenchHistory {

private Set<DbProgram> dbPrograms = new HashSet<DbProgram>(0);
private Set<DbUser> dbUsers = new HashSet<DbUser>(0);

public DbBench() {
}


public DbBench(Set<DbProgram> dbPrograms,
        Set<DbUser> dbUsers) {
    this.dbPrograms = dbPrograms;
    this.dbUsers = dbUsers;
}

//Getters/Setters

But I'm starting to think that I was wrong from the beginning and that inheritance was not the good way to handle this. If nothing shows up I will just go for BenchHistory - Bench being a simple one-to-one relationship

EDIT2 :

I edit while I can't answer my own question for insuficient reputation

I feel completly stupid now that I found the solution, that was so simple :

As I said, I was using hibernate managed methods : session.delete() or hql query. Hibernate was doing what he was supposed to do by deletintg the parent class, like it would have been in object inheritance.

So I just bypass hibernate by doing the deletion of the child class with one of the simplest SqlQuery on earth. And the base class entry remain untouched.

I understand that I somehow violate the object inheritance laws, but in my case it is really handy.

Thanks to everyone for your time, and believ me when I say I'm sorry.

È stato utile?

Soluzione

I don't think Hibernate/JPA supports this. What you basically want is conversion from a subclass to a superclass, and not a cascading delete. When you have an object of the subclass, the members from the superclass are treated no different than the members of the subclass.

This can be solved through writing some logic for it though:

public void deleteKeepSuperclassObject(final ChildData childData) {
    final BaseData baseDataToKeep = new BaseData();
    //populate baseDataToKeep with data from the childData to remove
    em.persist(baseDataToKeep);
    em.remove(childData);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top