JPA Entity inheritance with two DiscriminatorColumn - java

I need your help.
I have the following table of values that I want with JPA map.
I have considered the following class structure.
The classes "NotificationCustomShippingPlan" and "PreviewCustomShippingPlan" get everyone a DiscriminatorValue for DiscriminatorColumn "Type".
But the classes "ActivResultCustomShippingPlan" and "ActivResultCustomShippingPlan" should get other DiscriminatorColumn "SubType".
How can I so what map?
My feeling told me that it is not possible.
EDIT:
#Entity
#Inheritance
#DiscriminatorColumn(name = "TYPE")
#Table(name = "CC_CUSTOM_SHIPPING_PLAN")
public abstract class AbstractCustomShippingPlan {
....
....
}
#Entity
#DiscriminatorValue("NOTIFICATION")
public class NotificationCustomShippingPlan extends AbstractCustomShippingPlan
#Entity
#DiscriminatorValue("PREVIEW")
public class PreviewCustomShippingPlan extends AbstractCustomShippingPlan
#Entity
#DiscriminatorValue("RESULTS")
#DiscriminatorColumn(name = "SUBTYPE")
public abstract class ResultCustomShippingPlan extends AbstractCustomShippingPlan {
#Enumerated(EnumType.STRING)
#Column(name = "CC_CSP_SUBTYPE")
private ServiceType.Subtype subtype;
}
#Entity
#DiscriminatorValue("ACTIVE")
public class ActivResultCustomShippingPlan extends ResultCustomShippingPlan{
.....
}
#Entity
#DiscriminatorValue("REPORTED")
public class ReportedResultCustomShippingPlan extends ResultCustomShippingPlan {
....
}

Related

Problem with #UniqueConstraint with extends

Main class
#Entity
#Table(uniqueConstraints={#UniqueConstraint(columnNames={"codigoEAN", "tipo"})})
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "tipo")
#DiscriminatorValue("Produto")
public class Produto {
Class extending
#Entity
#DiscriminatorValue("Caixa")
public class ProdutosEmCaixa extends Produto {
What I wanted ?
That when it is a produto type "Produto" it does not repeat the keys (codigoEAN, tipo) but when it is of the type "Caixa" it can repeat the keys.
Something like
// That does not exist
#Table(uniqueConstraints={#UniqueConstraint(columnNames={"codigoEAN", "tipo=Produto"})})
Has anyone ever experienced this?
The problem is that you are using
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
This means that both entities will be mapped in a single table (using a discriminator column). You cannot define a unique constraint that only works for specific rows.
If the constraint only makes sense for a type of entity, you have to map them in separate tables.
With InheritanceType.TABLE_PER_CLASS:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Produto {
...
#Column(name="codigoEAN")
private String codigoEAN;
}
#Entity
#Table(uniqueConstraints={#UniqueConstraint(columnNames={"codigoEAN"})})
public class ProdutosEmCaixa extends Produto {
...
}
or InheritanceType.JOINED:
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "tipo")
#DiscriminatorValue("Produto")
public class Produto {
...
}
#Entity
#Table(uniqueConstraints={#UniqueConstraint(columnNames={"codigoEAN"})})
#DiscriminatorValue("Caixa")
public class ProdutosEmCaixa extends Produto {
...
#Column(name="codigoEAN")
private String codigoEAN;
}
See the Hibernate ORM documentation for more details about mapping inheritance.

Hibernate nested discriminator on inherited classes

I have 2 MYSQL tables
table1
id bigint auto increment Primary Key
type Enum ('vegetable','fruit')
color Enum ('green','red','yellow')
table2
id bigint (same as the id in Table 1)
sweet boolean
sour boolean
.. other fields specific to type fruit
Now I'm creating 3 objects, first the parent class
#Entity
#Configurable
#Table(name = "table1")
#DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
public class ParentClass {
..
}
Now the second class for vegetable
#Entity
#Configurable
#DiscriminatorValue("vegetable")
#DiscriminatorColumn(name = "color", discriminatorType = DiscriminatorType.STRING)
public class Vegetable extends Parent{
..
}
And thirdly, the fruit class
#Entity
#Configurable
#SecondaryTables({ #SecondaryTable(name = "table2",
pkJoinColumns = { #PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id") }) })
#DiscriminatorValue("fruit")
#DiscriminatorColumn(name = "color", discriminatorType = DiscriminatorType.STRING)
public class Fruit extends Parent{
..
}
I'm needing the second discriminator to add further inherited classes (6 further classes) on Vegetable and Fruit like,
#Entity
#Configurable
#DiscriminatorValue("red")
public class RedVegetable extends Vegetable{
..
}
#Entity
#Configurable
#DiscriminatorValue("green")
public class GreenFruit extends Fruit{
..
}
and so on.
Hibernate isn't letting me do that. What's wrong with my design? Thanks in advance!
Learnt this cannot be done in Hibernate. So found an alternate way to do things by merging the discriminator friends in table1 like Enum ('fruit|red', 'fruit|green', 'vegetable|red'.. & so on).
Please correct me if I was wrong.

Polymorphic query in spring data

I have one base abstract class.
#Entity
#Table(name = "P_FLD")
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "FLD_DISCRIMINATOR", columnDefinition = "CHAR(3)")
abstract public class AbstractPassbookField
and some classes that extends it. For example:
#Entity
#DiscriminatorValue("F")
#Table(name = "P_FLD_F")
public class PassbookFileField extends AbstractPassbookField
and i create repository for base entity
public interface PassbookRepository extends CrudRepository<AbstractPassbookField, Long>
I'm running next test
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:test-config.xml")
public class PassbookFieldRepositoryTest {
#Autowired
PassbookRepository passbookRepository;
#PersistenceContext
private EntityManager em;
#Test
public void testSave() {
PassbookFileField passbookFileField = new PassbookFileField();
passbookFileField.setFilename("text.test");
passbookFileField.setTemplate(true);
passbookFileField.setReadonly(true);
passbookFileField.setImageType(ImageType.I);
passbookFileField.setResoltuionType(ImageResolutionType.N);
passbookFileField = passbookRepository.save(passbookFileField);
passbookRepository.findAll();
}
}
passbookRepository.save(passbookFileField) - works well, but
passbookRepository.findAll() gives me an exception
org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: Object [id=1] was not of the specified subclass [ru.teamlabs.moneybox.commons.model.passbook.field.AbstractPassbookField] : Discriminator: F ; nested exception is org.hibernate.WrongClassException: Object [id=1] was not of the specified subclass [ru.teamlabs.moneybox.commons.model.passbook.field.AbstractPassbookField] : Discriminator: F
Quering through entityManager gives me the same error. What I'm doing wrong?
You haven't given the DiscriminatorValue value for your Super Class thus when retrieving it can not distinguish Super and Sub Classes. Try the following, it must work.
#Entity
#Table(name = "P_FLD")
#DiscriminatorValue("SF")
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "FLD_DISCRIMINATOR", columnDefinition = "CHAR(3)")
abstract public class AbstractPassbookField
I've found out why it was happening.
#DiscriminatorColumn(name = "FLD_DISCRIMINATOR", columnDefinition = "CHAR(3)")
This string was the problem.
In PassbookFileField i have
#DiscriminatorValue("F")
But repository expected to get entity with discriminator with 3 chars.
Such discriminator
#DiscriminatorValue("F")
or such discriminator column definition
#DiscriminatorColumn(name = "FLD_DISCRIMINATOR", columnDefinition = "CHARACTER VARYING(3)")
solves the problem

Override JPA MappedSuperClass generic property

I have the below scenario, I need sub-classes to be able to specify the actual types of properties found in MappedSuperClass(s). I use hibernate as a provider and I don't mind using hibernate specific annotations to solve this problem.
#MappedSuperclass
abstract class BaseA{
....
#OneToMany(mappedBy = "baseA")
public Set<? extends BaseB> getBaseB(){
.....
}
}
#MappedSuperclass
abstract class BaseB{
.....
#ManyToOne(optional = false)
#JoinColumn(name = "basea_id")
public BaseA getBaseA(){
.....
}
}
#Entity
class BaseAImpl extends BaseA{
public Set<BaseBImpl> getBaseB(){
.....
}
}
#Entity
class BaseBImpl{
public BaseAImpl getBaseA(){
.....
}
}
#AssociationOverride will hep you in this case. See the documentation for it (of course it is a JPA annotation). You could use it in combination with the #AttributeOverrides annotation for overriding basic types. Example (taken from the example):
#MappedSuperclass
public class Employee {
...
#ManyToOne
protected Address address;
...
}
#Entity
#AssociationOverride(name="address",
joinColumns=#JoinColumn(name="ADDR_ID"))
// address field mapping overridden to ADDR_ID foreign key
public class PartTimeEmployee extends Employee {
...
}

javax.persistence annotations and inheritance

I have 4 persistent classes which all have the same fields (exactly) the only 3 difference between them is 1) the class name, 2) the table name and 3) the data. i am aware that this might seem strange to some but trust me there is a good reason which i won't go into here.
now, i'm using hibernate annotations to configure my class which should work like so:
#Entity
#Table(name = "store")
public class Store
{
#Id
#Column(name = "unique_id")
protected String id;
#Column
protected String category;
...
}
.. and this does work, for a single stand-alone class, however there are many fields to map and i'd like to do it all in one hit for all four similar classes, ie:
public class StoreBase
{
#Id
#Column(name = "unique_id")
protected String id;
#Column
protected String category;
...
}
#Entity
#Table(name = "store1")
public class Store1 extends StoreBase
{}
#Entity
#Table(name = "store2")
public class Store2 extends StoreBase
{}
#Entity
#Table(name = "store3")
public class Store3 extends StoreBase
{}
#Entity
#Table(name = "store4")
public class Store4 extends StoreBase
{}
however when attempting this i get the following exception:
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: package.entities.Store1
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:672)
at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:546)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:291)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1292)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
i'm guessing this is because the super class is not being searched for the identifier?
is there a way to utilise inheritance in this context?
thanks, paul.
#MappedSuperclass
public class StoreBase
See docs for more info.
Have a look at #MappedSuperclass.

Categories