ebean-orm / ebean

Ebean ORM
https://ebean.io
Apache License 2.0
1.47k stars 260 forks source link

@Inheritance / DiscriminatorColumn stops working in EBean 15 (upgrade from 14) #3475

Open tbee opened 1 month ago

tbee commented 1 month ago

Given these classes:

@Entity
@Table(name = "product")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Product extends BaseWithSave<Product> implements RegistrationProduct, Transferable<ProductTO>, Auditable {
}
@Entity
@DiscriminatorValue("0")
public class OtherProduct extends Product {
}

The annotations are in the jakarta.persistence package.

Expected behavior

This should work:

  DB.find(Product.class).findList();

Actual behavior

java.lang.UnsupportedOperationException: cannot create entity bean for abstract entity Product
at deployment.ioserver.ear//io.ebeaninternal.server.deploy.BeanDescriptor.createEntityBean(BeanDescriptor.java:1405)
at deployment.ioserver.ear//io.ebeaninternal.server.deploy.BeanDescriptor.createEntityBean2(BeanDescriptor.java:1445)
at deployment.ioserver.ear//io.ebeaninternal.server.query.SqlTreeLoadBean$Load.initBeanType(SqlTreeLoadBean.java:129)
at deployment.ioserver.ear//io.ebeaninternal.server.query.SqlTreeLoadBean$Load.initialise(SqlTreeLoadBean.java:308)
at deployment.ioserver.ear//io.ebeaninternal.server.query.SqlTreeLoadBean$Load.perform(SqlTreeLoadBean.java:320)
at deployment.ioserver.ear//io.ebeaninternal.server.query.SqlTreeLoadBean.load(SqlTreeLoadBean.java:343)
at deployment.ioserver.ear//io.ebeaninternal.server.query.SqlTreeLoadRoot.load(SqlTreeLoadRoot.java:26)
at deployment.ioserver.ear//io.ebeaninternal.server.query.CQuery.readNextBean(CQuery.java:389)
at deployment.ioserver.ear//io.ebeaninternal.server.query.CQuery.hasNext(CQuery.java:466)
at deployment.ioserver.ear//io.ebeaninternal.server.query.CQuery.readCollection(CQuery.java:495)
at deployment.ioserver.ear//io.ebeaninternal.server.query.CQueryEngine.findMany(CQueryEngine.java:343)
at deployment.ioserver.ear//io.ebeaninternal.server.query.DefaultOrmQueryEngine.findMany(DefaultOrmQueryEngine.java:126)
at deployment.ioserver.ear//io.ebeaninternal.server.core.OrmQueryRequest.findList(OrmQueryRequest.java:380)
at deployment.ioserver.ear//io.ebeaninternal.server.core.DefaultServer.findList(DefaultServer.java:1329)
at deployment.ioserver.ear//io.ebeaninternal.server.core.DefaultServer.findList(DefaultServer.java:1311)
at deployment.ioserver.ear//io.ebeaninternal.server.querydefn.DefaultOrmQuery.findList(DefaultOrmQuery.java:1489)
at deployment.integration-test.war//com.nedap.healthcare.administration.finance.TestProductFinder.simple(TestProductFinder.java:38)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)```

Somehow it tries to instantiate the abstract class or something. Continuing the investigation

rbygrave commented 1 month ago

upgrade from 14

Ah no we literally can't upgrade to 15 with an application that uses @Inheritance. We have to keep those applications on 14, which is to say that 14 and 15 are the same but with various features removed from 15 and that includes support for @Inheritance which might sound drastic but there is some background reading referenced below.

Refer to: https://github.com/ebean-orm/ebean/releases/tag/15.0.0-RC

And refer to the discussions leading up to it at: https://github.com/ebean-orm/ebean/discussions/3112

So ponder those discussions etc but no we need to stay on 14 for apps using @inheritance [and this is why we need to keep releasing both 14 and 15 etc]. Also apologies because I need to improve 15 to better error when it detects inheritance mapping.

tbee commented 1 month ago

Oh my. I can understand you do not want to support all the more complex inheritance types, but single table is used a lot to do polymorphism: in this case have a generic product with 15 or so subtypes. It can just be some different behaviour, code only, but it is the natural (OOP) place for that code to live... And the ORM should return the correct class. Is it really so complex to instantiate and populate the correct class based on the discriminator?