I use EmailAlert bean as DTO to get data by means of Hibernate.
So, my class contains only fields that I have in DB.
But in some cases I need additional fields to be in EmailAlert to hold intermediate data. For example "caption" field - will be calculated on java side depends of user locale, time, etc.
So, I have some variants to solve this issue.
Add additional property (ex: caption) to EmailAlert bean, but do not map it with any field of DB table.
Drawback: In this case we have to do not use "caption" property in hashCode() and equals() because as:
It really don't have a matter - field holds only intermediate data
I am not sure it not be a cause of problem with cache and Hibernate itself.
I think it is very ugly to have a property of class but do not use it in equals() and hashCode() methods.
Someone can be confusing in the future with this logic.
Extend EmailAlert as EmailAlertExt with adding of "caption" property. And constructor that takes EmailAlert as argument.
But in this case I am not sure underwater stones in case I will store EmailAlert as EmailAlertExt bean again into DB.
Extend EmailAlert as EmailAlertExt2 with adding of "caption" property and take a refference to the original object. In this case EmailAlertExt2 will behave as original EmailAlert, but with additional property we need. In case we save EmailAlert we could call getOriginalValue() of EmailAlertExt2 that will return refference to original object.
Drawback: too many coding :)
Guys, which of these solutions is better? May be someone have other proposals?
Use '#Transient' it won't map to db hibernate will ignore this field
Extending a model object just because you want to separate mapped vs non-mapped fields is not a good idea. A good guideline would be to ask yourself the question "What is the difference between an EmailAlert and an EmailAlertX, and can I clearly define the situations where I would use one over the other?". If you cannot answer that question cleanly, or if you realize that you will always be using your subclass over the parent class, that is a sure sign that the parent class should be abstract or that you have too many classes.
In your particular case, it would make more sense to have both the mapped, and non-mapped properties on the same class, and to mark the non-mapped properties so that your ORM provider does not try to process them. You can do this by annotating these properties as being #Transient.
public class EmailAlert implements Serializable {
#Id
private Long id;
#Column(name = "recipient")
private String recipient;
#Transient
private transient String caption;
// Constructor, Getters/Setters, etc
}
Also, with respect to to your comment on hashcode/equals methods. You do not and should not include every property of a Java Bean in these methods. Only include those properties that are:
required to uniquely identify the object
are (fairly) guaranteed to have the same value over the lifecycle of the object
It sounds like the EmailAlert object you need at the moment is a business object, because of the "intermediate data" and "calculated on java side" bits.
Maybe use the EmailAlertDto object to populate the fields of the EmailAlertBusiness and store the extra caption field and the methods in the business object.
Related
I have an #Embeddable class with two fields: type and value. Both fields map to the corresponding database columns. The first one is enum and the latter one is an interface that has multiple implementations.
Only certain combinations of type and value are considered valid even if type and value are correct in isolation. How can I perform such validation, when I retrieve the entity that owns the #Embeddable from the database?
I could perform validation inside no-args-constructor of embeddable, but as far as I'm concerned, Hibernate creates new #Embeddable instance with no-args-constructor and then injects the values with Java Reflection API. Therefore, if I access these two fields inside the constructor they will be null.
Is there an approach to register some PostLoad hook for the #Embeddable classes that Hibernate will trigger? I though about declaring PostLoad inside the entity itself and then calling MyEmbeddable.validate directly. But I think it's a dirty approach.
I added the class-level annotation to validate the whole object. It did work. Check out this question for more details.
Suppose I have already made class which I wish to persist. I can't change it's code, i.e. can't put any annotations inside. Also, class is not following bean convention.
I.e. it is arbitrary complex class I wish to persist.
Is it possible to write some sort of custom serializer and deserializer (don't know how to name it) in Hibernate, so that I be able to read these classes as usual POJOs?
Hello the first question is can I map a "fina class" the answer to this question is YES as long as you dont use Hibernate Enchancing or some sort of instrumentation.
Now second question. Bean not following Bean Conventions. I guess this means no getters and setters. You can have Attribute level access so this is again not a problem.
Is it possible to write custom serializer in Hibernate. The answer here is NO. Why ? Because Hibernate is not about Serialization hibernate is about SQL. There is no strict requirement that a Hibernate Entity should be serialize-able.
Even though Hibernate does not enforce serialization. Can I still make my final class serialize-able even though it does not implement Serializable or Eternalizeable. Yes you need to wrap it into class implementing Serializable or Externalizeable and implement the doRead doWrite methods yourself.
Serialization to JSON or XML - this is not part of Hibernate neither is part of JPA. Serialization to these two formats is defined as part of the Jaxb and Jax-rs specifications.
Have a look at hibernate UserType and CompositeUserType, with the well known EnumUserType example
Enums are a bit like your needs : final class, no getters nor setters. They are not complex though, so you might need a CompositeUserType that allows to map several columns for one Type, rather that a UserType.
Then you would use it like that in your class :
public class MyClass {
#Id
private Long id;
#Type(type = "com...MyCompositeUserType")
private ComplexFinalClassNotPojo complexObject;
}
Assuming a JPA entity with (for example) an long id generated automatically:
#Entity
#AutoProperty
public class SomeItem {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long Id;
...
}
Is there any reason to not generate setter and getters for this Id? One might be tempted to not generate a setter for example, since it is the responsibility of JPA to generate the ID.
I see that other comments has misguided you so I feel myself obliged to elaborate on this issue a bit, even though I can't give you a scientific and complete answer. #vcetinick wrote the current accepted answer:
You may find that you may be able to get away [..] from the persistence side of things.
This quote in particular is wrong. All depends on where you put your #Id annotation. The specification says:
If the entity has field-based access, the persistence provider runtime
accesses instance variables directly.
Thus you are not required in any way to provide a setter or getter. Because you annotated your field and not a getter method (annotating the setter method will be ignored and have no bearing).
However, if you write a getter method, and annotated this method with your #Id annotation instead of your field, then we would tell our persistence provider to access our field through the accessor (getter) and mutator (setter) methods and not use reflection. In that case, both a getter and a setter should be present. The book Pro JPA 2: Mastering the Java™ Persistence API writes on page 71 (bold markup by me!):
When property access mode is used, the same contract as for JavaBeans applies, and there must be getter and setter methods for the persistent properties. The type of property is determined by the return type of the getter method and must be the same as the type of the single parameter passed into the setter method. Both methods must be either public or protected visibility.
Therefore, I usually annotate my id field, and write both a setter and getter method, but the setter method I give protected access. I just don't want any other pieces of code to have easy write access to such an important field. I don't know if this would cause problems in other domains. I'm no expert. But I don't find any rationale either as to why not setup an id attribute in this way. See also the Netbeans forums.
You may find that you may be able to get away without putting a getter/setter on the JPA Entity from the persistence side of things. But if you start dealing with entities that are serialized from other sources, even from your view in some cases, you will need a way to set the ID of the entity to let JPA know that it is dealing with an existing entity, if you cant set the id, then the persistence layer will just treat it as a new Object.
Id is your primary key without it you will never able to insert records in the database.
In your case #GeneratedValue(strategy=GenerationType.AUTO) it ensures that id will be generated for each persist but then also you will need a method to access it since it is primary identification of entity you should provide access to it .
Its like you asking some person his name and he doesn't provide it to you and you would thing he is just being rude .
Is it necessary to check all the field in equals method of model class in JPA, or can I use only id?
No, it's not necessary to put all of your fields in the equals method just because you're using JPA. In fact, JPA specific fields you may want to ignore.
You need to decide what makes most sense for your application, but it's quite common to exclude your #Id and #Version fields. Include only those fields that differentiate one instance of an object from another: essentially the fields that form the key.
Not always. You should clearly see which fields form a native (business) key and compare only those fields. Sometimes all fields form the native key, sometimes not.
Read this discussion at hibernate forum about strategies of implementing equals and hashcode.
I would check the id only. In case it's null (not set), which is the case for just created objects, I would rely on standard equals implementation (comparison of references).
Suppose, I have a lot of classes, which are constructed using Java reflection (for some reason). Now I need to post-inject values to fields, which are
annotated with #PostInject.
public class SomeClass {
#PostInject
private final String someString = null;
public void someMethod() {
// here, someString has a value.
}
}
My question is: what is a fast way to set a field using reflection?
Remember, I need to do this very often on a lot of classes, that's
why performance is relevant.
What I would do by intuition is shown by this pseudo-code:
get all fields of the class
clazz.getFields();
check, which are annotated with #PostInject
eachField.getAnnotation(PostInject.class);
make these fields accessible
eachAnnotatedField.setAccessible(true);
set them to a certain value
eachAnnotatedField.set(clazz, someValue);
I'm afraid that getting all fields is the slowest thing to do.
Can I someone get a field, when I know it from the beginning?
NOTE: I can't just let the classes implement some interface, which would
allow to set the fields using a method. I need POJOs.
NOTE2: Why I want post-field injection: From the point of view of an API user, it must be possible to use final fields. Furthermore, when the types and number of fields are not known by the API a priori, it is impossible to achieve field initialization using an interface.
NOTE2b: From the point of view of the user, the final contract is not broken. It stays final. First, a field gets initialized, then it can't be changed. By the way: there are a lot of APIs which use this concept, one of them is JAXB (part of the JDK).
How about doing steps 1 to 3 just after you constructed the object and saving the set of annotated fields that you obtain either in the object itself or by keeping a separate map of class to set-of-annotated-fields?
Then, when you need to update the injected fields in an object, retrieve the set from either the object or the seperate map and perform step 4.
Don't know if it's any good, but this project looks like it would do what you want. Quote:
A set of reflection utilities and
miscellaneous utilities related to
working with classes and their fields
with no dependencies which is
compatible with java 1.5 and generics.
The utilities cache reflection data
for high performance operation but
uses weak/soft caching to avoid
holding open ClassLoaders and causing
the caches to exist in memory
permanently. The ability to override
the caching mechanism with your own is
supported.
Another option, as you say you know the few fields concerned from the beginning, is to ask only for those fields or methods.
Example : see getDeclaredMethod or getDeclaredField in java/lang/Class.html
You can exploit existing frameworks that allow to inject dependencies on object construction. For example Spring allows to do that with aspectj weaving. The general idea is that you define bean dependencies at spring level and just mark target classes in order to advise their object creation. Actual dependency resolution logic is injected directly to the class byte-code (it's possible to use either compile- or load-time weaving).
Fastest way to do anything with reflection is to cache the actual Reflection API classes whenever possible. For example I very recently made a yet-another-dynamic-POJO-manipulator which I believe is one of those things everyone ends up doing at some point which enables me to do this:
Object o = ...
BeanPropertyController c = BeanPropertyController.of(o);
for (String propertyName : c.getPropertyNames()) {
if (c.access(propertyName) == null &&
c.typeOf(propertyName).equals(String.class)) {
c.mutate(propertyName, "");
}
}
The way it works is that it basically has that one controller object which lazyloads all the properties of the bean (note: some magic involved) and then reuses them as long as the actual controller object is alive. All I can say is that by just saving the Method objects themselves I managed to turn that thing into a damn fast thing and I'm quite proud of it and even considering releasing it assuming I can manage to sort out copyrights etc.