1

I'm having an issue with JPA. Basically, what I have is an entity with a list of an abstract type and I need each element of the list to be persisted in its corresponding table with a foreign key (to relate to the entity). Here is the code:

@Entity(name = "entity")
public class Entity{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private BigInteger id;

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name="entity_id", referencedColumnName="id")
private List<AbstractType> types;
}

Abstract type:

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractType{
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private BigInteger id;

private String someProp;

@Column(name="entity_id")
private BigInteger entityId;
}

Type A:

@Entity(name = "type_a")
@Transactional
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class TypeA extends AbstractType{
private String prop1;
private String prop2;
}

Type B:

@Entity(name = "type_b")
@Transactional
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class TypeB extends AbstractType{
private String prop3;
private String prop4;
}

I'm having a SQL error. The generated query tries to update the table of the abstract type (which shouldnt exist). This is part of the query:

update hibernate_sequences set sequence_next_hi_value = ? where 
sequence_next_hi_value = ? and sequence_name = 'abstract_type'
insert into type_a (some_prop, entity_id, prop1, prop2) values (?, ?, ?, ?)
insert into type_b (some_prop, entity_id, prop3, prop4) values (?, ?, ?, ?)
update abstract_type set entity_id=? where id=?

As you can see, it's trying to update a table which doesn't (and shouldnt) exist. 'abstract_type' table.

Thanks in advance.

Mac
  • 51
  • 1
  • 4
  • It's the same problem: http://stackoverflow.com/q/3557879/2387977 – Dherik Mar 15 '16 at 00:53
  • If something is abstract, using @MappedSuperclass makes more sense. Inheritance is specified ONCE in the root class. You don't need to re-specify it in subclasses! – Neil Stockton Mar 15 '16 at 09:37
  • @Dherik, maybe is the same problem, but that solution didn't work for me. That approach doesn't save the FKs in the tables of the concrete classes. – Mac Mar 15 '16 at 14:28
  • @NeilStockton, I know I should use MappedSuperclass, but that doesn't work. Thats because my list is of that abstract type and it tries to find the abstract type entity and it doesn't exist if you use that annotation. – Mac Mar 15 '16 at 14:34
  • You mean "it doesn't work in Hibernate"? It does in other JPA implementations. – Neil Stockton Mar 15 '16 at 14:38
  • http://stackoverflow.com/questions/9873547/how-to-map-an-abstract-collection-with-jpa – Mac Mar 15 '16 at 15:15

1 Answers1

0

Of course you can't name a class Entity without causing problems.

You can make this much simpler by minimizing the annotations and let JPA do it's work. A Container class holds a collection of AbstractTypes:

@Entity
public class Container {
    @Id @GeneratedValue
    private Long id;

    @OneToMany(cascade=CascadeType.ALL)
    private List<AbstractType> types;

    public List<AbstractType> getTypes() { return types; }
    public void setTypes(List<AbstractType> types) { this.types = types; }
}

The AbstractType is just that:

@Entity
public abstract class AbstractType {
    @Id @GeneratedValue
    private Long id;
}

And a couple concrete types to extend and inherit from the abstract superclass: EDIT: A FK back to the Container class can be added with a ManyToOne association.

@Entity
public class TypeA extends AbstractType {
@ManyToOne
private Container container;

}

And:

@Entity
public class TypeB extends AbstractType {    
@ManyToOne
private Container container;
}

When I run this Minimal, Complete, Verifiable Example I get the following output:

Hibernate: create table AbstractType (DTYPE varchar(31) not null, id bigint not null, container_id bigint, primary key (id))
Hibernate: create table Container (id bigint not null, primary key (id))
Hibernate: create table Container_AbstractType (Container_id bigint not null, types_id bigint not null)

Hibernate: insert into Container (id) values (?)
Hibernate: insert into AbstractType (container_id, DTYPE, id) values (?, 'TypeA', ?)
Hibernate: insert into AbstractType (container_id, DTYPE, id) values (?, 'TypeB', ?)
Hibernate: insert into Container_AbstractType (Container_id, types_id) values (?, ?)
Hibernate: insert into Container_AbstractType (Container_id, types_id) values (?, ?)
Hibernate: select container0_.id as id1_1_ from Container container0_

model.Container@40591559
Community
  • 1
  • 1
K.Nicholas
  • 10,956
  • 4
  • 46
  • 66