How to override parameter in sublass of #MappedSuperclass - java

I have a MappedSuperclass
#MappedSuperclass
public class A{
.
.
.
#Column(name="something")
public getSomething(){..};
public setSomething(){..};
}
I want to override the something in a subclass
#Entity
public class B{
#Override
public getSomething(){..};
}
but getting Caused by: org.hibernate.MappingException: Duplicate property mapping of data found Exception
I tried different things like "#AttributeOverride" annotation, but it didn't help.
The only solution i know is to make something Transient in the mappedSuperclass. But i don't want that it will be transient here (because there is another subclasses that don't want to override something but want that it will be transient)

Two solutions occur to me: one is to maybe break this SuperClass up and use Emmbeddeds to create the hierarchy you want. If you want to stick with this approach though, I think you need to override using #AttributeOverride both the property and the method like this in the subclass:
#Entity
public class B {
#AttributeOverride(name = "fred", column = #Column(name = "FRED"))
private Integer fred;
#Override
public Integer getFred() {return fred;}
}

Related

JPA OneToMany Association from superClass

I’m trying to map the inheritance from the superclass LendingLine and the subclasses Line and BlockLine. LendingLine has an ManyToOne association with Lending.
When I try to get the LendingLines from the database without the inheritance it works fine. The association works also. But when i add the inheritance, lendingLines in Lending is empty. I also can't get any LendingLines from the DB with the inheritance.
Can anybody help me?
(Sorry for the bad explanation)
Thanks in advance!
LendingLine:
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="TYPE")
#DiscriminatorValue(value="Line")
#Table(name = "LendingLine")
public class LendingLine {
...
public LendingLine(){}
#ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER, targetEntity=Lending.class)
#JoinColumn(name = "LendingId")
private Lending lending;
...
Lending:
#Entity
#Table(name = "Lending")
public class Lending {
...
public Lending(){}
#OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER, mappedBy = "lending")
private List<LendingLine> lendingLines;
...
BlockDate:
#Entity
#DiscriminatorValue(value = "BlockLine")
public class BlockLine extends LendingLine {
public BlockLine(){
}
}
LendingLineRepository:
This class only reads from the db because the db was created by another application ( C#) where the objects are added to the db.
public class LendingLineRepository extends JpaUtil implement LendingLineRepositoryInterface {
#Override
protected Class getEntity() {
return LendingLine.class;
}
#Override
public Collection<LendingLine> findAll() {
Query query = getEm().createQuery("SELECT l FROM LendingLine l");
System.out.println(query.getResultList().size());
return (Collection<LendingLine>) query.getResultList();
}
Table LendingLine:
Choose your type of superclass according to your needs:
Concrete Class
public class SomeClass {}
Define your superclass as a concrete class, when you want to query it and when you use a new operator for further logic. You will always be able to persist it directly. In the discriminator column this entity has it's own name. When querying it, it returns just instances of itself and no subclasses.
Abstract Class
public abstract class SomeClass {}
Define your superclass as an abstract class when you want to query it, but don't actually use a new operator, because all logic handled is done by it's subclasses. Those classes are usually persisted by its subclasses but can still be persisted directly. U can predefine abstract methods which any subclass will have to implement (almost like an interface). In the discriminator column this entity won't have a name. When querying it, it returns itself with all subclasses, but without the additional defined information of those.
MappedSuperclass
#MappedSuperclass
public abstract class SomeClass {}
A superclass with the interface #MappedSuperclass cannot be queried. It provides predefined logic to all it's subclasses. This acts just like an interface. You won't be able to persist a mapped superclass.
For further information: JavaEE 7 - Entity Inheritance Tutorial
Original message
Your SuperClass LendingLine needs to define a #DiscriminatorValue as well, since it can be instantiated and u use an existing db-sheme, where this should be defined.

Embedded single table mapping

I'm facing an issue with modelling hibernate mapping. Here is what i have:
#Entity
#Table
public class Entry {
#Id private long id;
#Embedded private Content content;
...
}
#MappedSuperclass
#DiscriminatorColumn(name="content_type")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Content {
#Column(name="content_type") private String type;
...
}
#Embeddable
#DiscriminatorValue("A")
public class AContent extends Content {
...
}
#Embeddable
#DiscriminatorValue("B")
public class BContent extends Content {
...
}
I'd like to have that all subclasses of Content to be mapped as embedded onto the Entry class.
In other words, in result i'd like to have one Entry table with columns from all subclasses of Content.
Currently the persisting Entry test says that:
javax.persistence.PersistenceException: org.hibernate.InstantiationException:
Cannot instantiate abstract class or interface: : foo.bar.Content
So it seems that loading fails because instead of getting AContent it tries to instantiate abstract Content.
Any ideas?
Spec says...
An entity may inherit from another entity class. Entities support inheritance, polymorphic associations and polymorphic queries.
It says nothing about embeddables being inheritable and thus has no support for inheritance for them.

Create index on field from parent class

I have problem with adding index. I use hibernate with annotation driven configuration.
I have something like this:
#MappedSuperclass
public abstract class BaseEntity {
#Id
private String id;
private String profileId;
...
//getters and setters
}
and several child classes
#Table(name="note")
public abstract class Note extends BaseEntity{
//different fields
}
#Table(name="message")
public abstract class Message extends BaseEntity{
//different fields
}
I want to add index to field "profileId" in class BaseEntity. But if I do so, with annotation #Index(name="profileid_index"), it creates only for table "note", and fails on "message", because index "profileid_index" already exist.
I did not find way, how to make hibernate generate unique index names. Or may be someone knows another solution how to index field in parent class.
Did you have a look on #Tables annotation: http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/ ?
You can do stuff like:
#Tables(value={#Table(appliesTo="table1", indexes={#Index(name="index1", columnNames={"column1", "column2"})}),
#Table(appliesTo="table2", indexes={#Index(name="index1", columnNames={"column1", "column2"})})})
Should help in your case if you put this annotation to your #MappedSuperclass, although I don't know if there is a more cleaner solution
Being more precise, you could try for your case:
#Tables(value={#Table(appliesTo="note", indexes={#Index(name="index_profile_id1", columnNames={"profileId"})}),
#Table(appliesTo="message", indexes={#Index(name="index_profile_id2", columnNames={"profileId"})})})

MySQL tables for abstract/concrete classes using Hibernate for ORM

I have the following classes:
public abstract class Generic(){
private int Id;
...
}
public class ExtA extends Generic(){
private Generic fieldA();
private Generic fieldB();
...
}
public class ExtB extends Generic(){
private Generic fieldA;
....
}
public class ExtC extends Generic(){
...
}
Sorry for the vague example.
I am trying to find a way to save those objects to the database, but can't seem to find a good way. I wish to have separate tables for ExtA, ExtB, ExtC, and then use foreign keys to relate the contained fields. I am using MySQL, and working with Java, Spring, Hibernate. Can someone please show me an example of how to do this, or point me to some tutorial?
I should mention I am new at working with databases.
Something like this. i'm relatively sure the Table_Per_Class strategy will let you ask for any "Generic" object and query all it's subclass tables. Keep in mind if you do this, the ID should be unique across all of your subclass types. You'll have to figure out a strategy for this use the right annotations to tell hibernate what to do. But in the mean time, this example assumes you're assigning it manually before saving.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Generic {
#Id #Column(name="ID")
private Long id;
...
}
#Entity
#Table(name="EXTA")
public class ExtA extends Generic {
#Column(name="fieldA")
private Generic fieldA;
}

Why #OneToMany does not work with inheritance in Hibernate

#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Problem {
#ManyToOne
private Person person;
}
#Entity
#DiscriminatorValue("UP")
public class UglyProblem extends Problem {}
#Entity
public class Person {
#OneToMany(mappedBy="person")
private List< UglyProblem > problems;
}
I think it is pretty clear what I am trying to do. I expect #ManyToOne person to be inherited by UglyProblem class. But there will be an exception saying something like: "There is no such property found in UglyProblem class (mappedBy="person")".
All I found is this. I was not able to find the post by Emmanuel Bernard explaining reasons behind this.
Unfortunately, according to the Hibernate documentation "Properties from superclasses not mapped as #MappedSuperclass are ignored."
Well I think this means that if I have these two classes:
public class A {
private int foo;
}
#Entity
public class B extens A {
}
then field foo will not be mapped for class B. Which makes sense. But if I have something like this:
#Entity
public class Problem {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
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;
}
}
#Entity
public class UglyProblem extends Problem {
private int levelOfUgliness;
public int getLevelOfUgliness() {
return levelOfUgliness;
}
public void setLevelOfUgliness(int levelOfUgliness) {
this.levelOfUgliness = levelOfUgliness;
}
}
I expect the class UglyProblem to have fileds id and name and both classes to be mapped using same table. (In fact, this is exactly what happens, I have just checked again). I have got this table:
CREATE TABLE "problem" (
"DTYPE" varchar(31) NOT NULL,
"id" bigint(20) NOT NULL auto_increment,
"name" varchar(255) default NULL,
"levelOfUgliness" int(11) default NULL,
PRIMARY KEY ("id")
) AUTO_INCREMENT=2;
Going back to my question:
I expect #ManyToOne person to be inherited by UglyProblem class.
I expect that because all other mapped fields are inherited and I do not see any reason to make this exception for ManyToOne relationships.
Yeah, I saw that. In fact, I used Read-Only solution for my case. But my question was "Why..." :). I know that there is an explanation given by a member of hibernate team. I was not able to find it and that is why I asked.
I want to find out the motivation of this design decision.
(if you interested how I have faced this problem: I inherited a project built using hibernate 3. It was Jboss 4.0.something + hibernate was already there (you'd download it all together). I was moving this project to Jboss 4.2.2 and I found out that there are inherited mappings of "#OneToMany mappedBy" and it worked fine on old setup...)
In my case I wanted to use the SINGLE_TABLE inheritance type, so using #MappedSuperclass wasn't an option.
What works, although not very clean, is to add the Hibernate proprietary #Where clause to the #OneToMany association to force the type in queries:
#OneToMany(mappedBy="person")
#Where(clause="DTYPE='UP'")
private List< UglyProblem > problems;
I think it's a wise decision made by the Hibernate team. They could be less arrogante and make it clear why it was implemented this way, but that's just how Emmanuel, Chris and Gavin works. :)
Let's try to understand the problem. I think your concepts are "lying". First you say that many Problems are associated to People. But, then you say that one Person have many UglyProblems (and does not relate to other Problems). Something is wrong with that design.
Imagine how it's going to be mapped to the database. You have a single table inheritance, so:
_____________
|__PROBLEMS__| |__PEOPLE__|
|id <PK> | | |
|person <FK> | -------->| |
|problemType | |_________ |
--------------
How is hibernate going to enforce the database to make Problem only relate to People if its problemType is equal UP? That's a very difficult problem to solve. So, if you want this kind of relation, every subclass must be in it's own table. That's what #MappedSuperclass does.
PS.: Sorry for the ugly drawing :D
Unfortunately, according to the Hibernate documentation "Properties from superclasses not mapped as #MappedSuperclass are ignored." I ran up against this too. My solution was to represent the desired inheritance through interfaces rather than the entity beans themselves.
In your case, you could define the following:
public interface Problem {
public Person getPerson();
}
public interface UglyProblem extends Problem {
}
Then implement these interfaces using an abstract superclass and two entity subclasses:
#MappedSuperclass
public abstract class AbstractProblemImpl implements Problem {
#ManyToOne
private Person person;
public Person getPerson() {
return person;
}
}
#Entity
public class ProblemImpl extends AbstractProblemImpl implements Problem {
}
#Entity
public class UglyProblemImpl extends AbstractProblemImpl implements UglyProblem {
}
As an added benefit, if you code using the interfaces rather than the actual entity beans that implement those interfaces, it makes it easier to change the underlying mappings later on (less risk of breaking compatibility).
I think you need to annotate your Problem super-class with #MappedSuperclass instead of #Entity.
I figured out how to do the OneToMany mappedBy problem.
In the derived class UglyProblem from the original post. The callback method needs to be in the derived class not the parent class.
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#ForceDiscriminator
public class Problem {
}
#Entity
#DiscriminatorValue("UP")
public class UglyProblem extends Problem {
#ManyToOne
private Person person;
}
#Entity
public class Person {
#OneToMany(mappedBy="person")
private List< UglyProblem > problems;
}
Found the secret sauce for using Hibernate at least. http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/ForceDiscriminator.html The #ForceDiscriminator makes the #OneToMany honor the discriminator
Requires Hibernate Annotations.
In my opinion #JoinColumn should at least provide an option to apply the #DiscriminatorColumn = #DiscriminatorValue to the SQL "where" clause, although I would prefer this behaviour to be a default one.
I am very surprised that in the year 2020 this is still an issue.
Since this object design pattern is not so rare, I think it is a disgrace for JPA not yet covering this simple feature in the specs, thus still forcing us to search for ugly workarounds.
Why must this be so difficult? It is just an additional where clause and yes, I do have a db index prepared for #JoinColumn, #DiscriminatorColumn combo.
.i.. JPA
Introduce your own custom annotations and write code that generates native queries. It will be a good exercise.

Categories