Persist functor in a realtional database - java

I have a Java Entity that has several well defined functors. I want to persist them so as not factorize the object once it is fetched from the database. Is there a way to do so with Ebean?
I think that I could get it saving the class name that implements those functors as a String in the entity and in the setter of that string implement the setter of the functor with Reflection. Any other idea?
Class Example:
#Entity
public Foo extends Model
{
#Id
private Long id;
#Transient
private Runnable functor;
private String classFunctor;
public void setClassFunctor(String value)
{
//Here I implement the Reflection routine to load the functor.
}
}

Related

Using Java records as JPA embeddables

I want to use Java records as embeddable objects with JPA. For example I want to wrap the ID in a record to make it typesafe:
#Entity
public class DemoEntity {
#EmbeddedId
private Id id = new Id(UUID.randomUUID());
#Embeddable
public static record Id(#Basic UUID value) implements Serializable {}
}
But If I try to persist it with Hibernate 5.4.32 I get the following error:
org.hibernate.InstantiationException: No default constructor for entity: : com.example.demo.DemoEntity$Id
at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:85) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.tuple.component.AbstractComponentTuplizer.instantiate(AbstractComponentTuplizer.java:84) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
...
So it looks like Hibernate would treat the record Id like an entity, although it is an #Embeddable.
The same happens with non-id fields and #Embedded:
#Embedded
private Thing thing = new Thing("example");
#Embeddable
public static record Thing(#Basic String value) implements Serializable {}
Is there a way to use #Embeddable records with JPA/Hibernate?
Java records with a single field can be used for custom ID types or any other value object with AttributeConverters.
In the entity class the ID type is used with #Id as usual:
#Entity
public class DemoEntity {
#Id
private Id id = new Id(UUID.randomUUID());
public static record Id(UUID value) implements Serializable {}
}
Note that the record Id doesn't have any annotation.
The converter makes it possible to use records:
#Converter(autoApply = true)
public class DemoEntityIdConverter implements AttributeConverter<DemoEntity.Id, String> {
#Override
public String convertToDatabaseColumn(DemoEntity.Id id) {
return id.value().toString();
}
#Override
public DemoEntity.Id convertToEntityAttribute(String s) {
return new DemoEntity.Id(UUID.fromString(s));
}
}
Don't forget to set autoApply = true to have this converter applied automatically (without referencing it explicitly on the respective field).
Records with more than one field could be mapped with a Hibernate UserType, but that is a bit cumbersome.
Entity or embeddable, in any case the record class wouldn't be suitable here because entities and their fields, including embeddable ones, are modifiable. The only exception would be for Id fields, but that doesn't seem like an important enough case to make this functionality for.
One of the Hibernate developers explains this here

Persistent Model to Domain Model mapping without exposing domains object attributes

I know this is a common question, but I haven't found another that solves my doubts.
Usually, if the project is small, I've persistence annotations in the same object that represents the domain object. This allows to load the entity from database and keep all the setters private, ensuring any instance is always in a valid state. Something like:
#Entity
class SomeEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String attribute1;
private String attribute2;
private String attribute3;
// ... other attributes
protected SomeEntity() {}
/* Public getters */
public Long getId() { ... }
public String getAttribute1() { ... }
public String getAttribute2() { ... }
/* Expose some behaviour */
public void updateAttributes(String attribute1, String attribute2) {
/* do some validations before updating */
}
}
My problem appears if I want to hava a different persistent model. Then I would have something like:
/* SomeEntity without persistent info */
class SomeEntity {
private Long id;
private String attribute1;
private String attribute2;
private String attribute3;
// ... other attributes
protected SomeEntity() {}
/* Public getters */
public Long getId() { ... }
public String getAttribute1() { ... }
public String getAttribute2() { ... }
/* Expose some behaviour */
public void updateAttributes(String attribute1, String attribute2) {
/* do some validations before updating */
}
}
and DAO:
#Entity
class SomeEntityDAO {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String attribute1;
private String attribute2;
private String attribute3;
public SomeEntityDAO() {}
/* All getters and setters */
}
My question is, how can I map SomeEntityDAO to SomeEntity without exposing SomeEntity's attributes?
If I create a constructor like: public SomeEntity(String attribute1, String attribute2, ...) {}, then anyone can create an invalid instance of SomeEntity. The same occurs if I make all setters public in SomeEntity.
I also don't think is a valid solution build the object using updateAttributes() since this will execute some validations I don't whant to execute at this point (we trust the data that's persistet in database).
I'm thinking in having all the setters protected, so the DAO can extend the Entity and have access to setters... but I'm not sure if this is a good option.
Which is the best or common approach to solve this problem?
I've had the same kind of problem. And looking around I've found no solution. Believe me, if it exists is well hidden somewhere. None that suggests what to do when you have to deal with an old project where ORM entities are everywhere and there's a big step between Domain and ORM model.
Given this, I've deducted that if you really want to keep your Domain entities pure (so non get and set - the latter I would NEVER accept!) you have to do some deals. Because there's no way to share the internals without giving the entities some extra knowledge. Beware, this doesn't mean that you have to make the Domain entities aware of the ORM layer, nor that you have to use getters. Just, what I've concluded, the Domain entities should have ways to expose them as a different model.
So, in conclusion, what I would do in your situation is to build up a Visitor pattern. The Domain entity EntityA would implement the EntityAVisitable interface to accept a EntityAVisitor or something like this.
interface EntityAVisitable {
accepts(EntityAVisitor visitor);
}
The builder implements the interface required by the Visitor, EntityAVisitor.
interface EntityAVisitor<T>{
setCombinedValue1_2(String attribute1_attribute2_combinedInEntity);
<T> build();
}
The build() function of the interface EntityAVisitor uses a generic type T. In this way the Domain entity is agnostic about the return type of the concrete implementation of the EntityAVisitor.
Is it perfect? No.
Perfect solution would be to get rid of the ORM (actually I would say that I hate them, because the way are used is most of the times wrong - but this is my personal thought).
Is it nice? No.
A nice solution is not allowed due to language restrictions (I suppose you use Java).
Does it a good work in encapsulating the real content of your Domain entity? Yes.
Not only, in this way you can decide exactly what could be exposed and how. So, in my opinion, is a good deal between keeping the entity pure and having to work with an ORM under the seat.
Domain entity should be self-validating meaning it should only validate itself based on it's internal values. If update requires validation that depends on external dependencies, then I would create an updater class that is responsible for the update. From the updater class, you can use specification pattern (as an injectable dependency) to implement the validation.
Use domain entities when modifying, and DTOs for read-only projections. There are performance and simplification gains when you use straight DTOs in read-only. This is used in CQRS patterns.
class SomeEntity {
private Long id;
private String attribute1;
private String attribute2;
private String attribute3;
// ... other attributes
public SomeEntity() {}
/* Public getters/setter */
public Long getId() { ... }
public String getAttribute1() { ... }
public String getAttribute2() { ... }
public Long setId() { ... }
public String setAttribute1() { ... }
public String setAttribute2() { ... }
}
//classes/interfaces named for clarity
class EntityUpdater implements IEntityUpdater {
public EntityUpdater (ISpecification spec){
}
public updateEntity(SomeEntity entity){
//assert/execute validation
}
}
Some ORMs allow setting entity values through field access (as opposed to setter methods).
JPA uses the #Access annotation. See What is the purpose of AccessType.FIELD, AccessType.PROPERTY and #Access
I created an ORM, sormula, that can use field access. See #Row fieldAccess and test case org.sormula.tests.fieldaccess.

how to model a singleton object to table through hibernate?

I have a global config object in my project and there can ever be 0 or 1 instance of this class that i want to persist in db. What is the best way to do this ? One trick i know here is to have a "constant" field mapped with unique constraint set on it, are there other such ways as this looks a little hacky ?
Here's what i tried :-
#Entity
public class DTLdapConfig implements Serializable {
#GeneratedValue(strategy=GenerationType.TABLE)
#Id
private int id;
#Column(unique=true)
private boolean singletonGuard;
// no public setter getter for singletonGuard
// other code below
}

Composite Keys in DataNucleus JDO implementation (field jdoStateManager)

I'm trying to create a PK class for a JDO Entity named Item. It's was soo simple with JPA, but now im practicing JDO. I'm using anotation configuration and this is how the two classes look like:
#PersistenceCapable(table="ITEM",identityType = IdentityType.APPLICATION,
objectIdClass = ItemPK.class,schema="mgr")
public class Item {
#PrimaryKey
#Persistent(column="code")
private long code; //WHY public?
#PrimaryKey
#Persistent(column="producer")
private String producer;
#PrimaryKey
#Embedded
private ItemPK id;
#Persistent(column="price")
private double price;
#Persistent(column="name")
private String name;
#Persistent(column="description")
private String description;
[... getters/setters...]
}
I want the ItemPK class to be used as a Primary Key class with thoose two columns (code,producer). So this is how the class looks like:
#EmbeddedOnly
#PersistenceCapable(embeddedOnly="true",identityType=IdentityType.APPLICATION)
public class ItemPK implements Serializable{
#Persistent
#PrimaryKey
public long code;
#Persistent
#PrimaryKey
public String producer;
#Override
public String toString() {
return code+"_"+producer;
}
#Override
public int hashCode() {
[...Eclipse autogenerated...]
}
#Override
public boolean equals(Object obj) {
[...Eclipse autogenerated...]
}
}
What I do get after trying to run the code:
[...Caused by]
Nested Throwables StackTrace:
Class pl.edu.pw.mini.entity.jdo.Item has been specified with an object-id class pl.edu.pw.mini.entity.jdo.ItemPK which has a field jdoStateManager which isnt Serializable. All non static fields of an objectId class must be serializable.
org.datanucleus.metadata.InvalidPrimaryKeyException: Class pl.edu.pw.mini.entity.jdo.Item has been specified with an object-id class pl.edu.pw.mini.entity.jdo.ItemPK which has a field jdoStateManager which isnt Serializable. All non static fields of an objectId class must be serializable.
As I understand the enhancer adds jdoStateManager to a ItemPK, ad it is not Serializable. But as ItemPK is embedded, either it should not get the jdoStateManager, or JDO should know the difference between jdoStateManager and a regular field. What am I doing wrong to get an embedded class for a 2-column Primary Key
I have no Idea how to make this thing work, can anyone help me, and tell me what am I doing wrong here?
The docs define perfectly well how to do that
http://www.datanucleus.org/products/accessplatform_3_1/jdo/orm/compound_identity.html
and it doesn't involve use of #Embedded

Problem persisting inheritance tree

I have a problem trying to map an inheritance tree. A simplified version of my model is like this:
#MappedSuperclass
#Embeddable
public class BaseEmbedded implements Serializable {
#Column(name="BE_FIELD")
private String beField;
// Getters and setters follow
}
#MappedSuperclass
#Embeddable
public class DerivedEmbedded extends BaseEmbedded {
#Column(name="DE_FIELD")
private String deField;
// Getters and setters follow
}
#MappedSuperclass
public abstract class BaseClass implements Serializable {
#Embedded
protected BaseEmbedded embedded;
public BaseClass() {
this.embedded = new BaseEmbedded();
}
// Getters and setters follow
}
#Entity
#Table(name="MYTABLE")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="TYPE", discriminatorType=DiscriminatorType.STRING)
public class DerivedClass extends BaseClass {
#Id
#Column(name="ID", nullable=false)
private Long id;
#Column(name="TYPE", nullable=false, insertable=false, updatable=false)
private String type;
public DerivedClass() {
this.embedded = new DerivedClass();
}
// Getters and setters follow
}
#Entity
#DiscriminatorValue("A")
public class DerivedClassA extends DerivedClass {
#Embeddable
public static NestedClassA extends DerivedEmbedded {
#Column(name="FIELD_CLASS_A")
private String fieldClassA;
}
public DerivedClassA() {
this.embedded = new NestedClassA();
}
// Getters and setters follow
}
#Entity
#DiscriminatorValue("B")
public class DerivedClassB extends DerivedClass {
#Embeddable
public static NestedClassB extends DerivedEmbedded {
#Column(name="FIELD_CLASS_B")
private String fieldClassB;
}
public DerivedClassB() {
this.embedded = new NestedClassB();
}
// Getters and setters follow
}
At Java level, this model is working fine, and I believe is the appropriate one. My problem comes up when it's time to persist an object.
At runtime, I can create an object which could be an instance of DerivedClass, DerivedClassA or DerivedClassB. As you can see, each one of the derived classes introduces a new field which only makes sense for that specific derived class. All the classes share the same physical table in the database. If I persist an object of type DerivedClass, I expect fields BE_FIELD, DE_FIELD, ID and TYPE to be persisted with their values and the remaining fields to be null. If I persist an object of type DerivedClass A, I expect those same fields plus the FIELD_CLASS_A field to be persisted with their values and field FIELD_CLASS_B to be null. Something equivalent for an object of type DerivedClassB.
Since the #Embedded annotation is at the BaseClass only, Hibernate is only persisting the fields up to that level in the tree. I don't know how to tell Hibernate that I want to persist up to the appropriate level in the tree, depending on the actual type of the embedded property.
I cannot have another #Embedded property in the subclasses since this would duplicate data that is already present in the superclass and would also break the Java model.
I cannot declare the embedded property to be of a more specific type either, since it's only at runtime when the actual object is created and I don't have a single branch in the hierarchy.
Is it possible to solve my problem? Or should I resignate myself to accept that there is no way to persist the Java model as it is?
Any help will be greatly appreciated.
Wow. This is the simplified version? I assume that the behavior that you are seeing is that BaseEmbedded field is persisted but not the FIELD_CLASS_A or B?
The problem is that when Hibernate maps the DerivedClassA and B classes, it reflects and sees the embedded field as a BaseEmbedded class. Just because you then persist an object with the embedded field being a NestedClass, the mapping has already been done and the FIELD_CLASS_A and B are never referenced.
What you need to do is to get rid of the NestedClass* and embedded field and instead have the fieldClassA and B be normal members of DerivedClassA and B. Then add add a name field to the #Entity which will put them both in the same table I believe. This will allow you to collapse/simplify your class hierarchy a lot further.
See: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e1168
#Entity(name = "DerivedClass")
#DiscriminatorValue("A")
public class DerivedClassA extends DerivedClass {
#Column(name="FIELD_CLASS_A")
private String fieldClassA;
...
#Entity(name = "DerivedClass")
#DiscriminatorValue("B")
public class DerivedClassB extends DerivedClass {
#Column(name="FIELD_CLASS_B")
private String fieldClassB;
...

Categories

Resources