I have a model object that's in fact an enum with fields and getters:
#Entity
public enum Type {
TYPE1, TYPE2, TYPE3, TYPE4;
#Column
private Long id;
#Column
private String name;
...
public String getName() {
return this.name;
}
...
}
It compiles and runs fine. However, if I call a getter method, it returns null (it doesn't load any values stored in the database). Is this the standard behavior? Is there a way to make JPA load them?
I'd say there is some misconception in this aproach:
Entities represent objects that can be stored in the database. In this case, the database (or any other persistent store) defines which instances are available.
Enums represent a fixed set of constants that are defined in source code. Thus the class itself defines which constants are available. In addition, it's generally bad practice to change the values of an enum, i.e. the name or id in your case.
You see that they are two quite different concepts which should be treated differently.
To store enums in entities (where the enum is a field of that entity), you could either use #Enumerated and store the name or ordinal of the enum, or (what we do more often) store one of the fields (we mostly use the id) and provide conversion methods.
If you want to store configurable "constants" in the database you might try and use plain entities for that, make the constructor private (Hibernate and other JPA providers should be able to deal with that) and provide an alternative implementation of the Enum class (you can't use the enum keyword though).
Have you looked into the #Enumerated annotation? I haven't ever tried to use it within an enum itself, however it works quit well binding a class property to an enum.
enum Type{TYPE1, TYPE2}
#Column(name="type")
#Enumerated(EnumType.STRING)
public Type getType(){return type;}
public void setType(Type t){type = t;}
If JPA cannot be made to handle this, you could add a public Type valueOf(long id) method to your enum class which you use as a factory to instantiate enum instances representing the values in your legacy table.
Related
If I'm using JPA's annotations to specify my mapped fields, like so:
public class PersistedEmployee {
private Integer id;
#Id//Plus some #GeneratedValue cruft in the real example
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
}
Does that ID need to follow the getFoo bean naming convention? Or are the annotations sufficient for identifying how to map this POJO?
The underlying provider is Hibernate, in this case, but I'm also curious if that makes a difference or not.
JPA supports two ways to access properties. Either through getters and setters or through reflection directly accessing the field.
If you use the first, the getters and setters need to follow the proper naming convention, if you use the second, they don't have to exist, and you can use whatever accessors/mutator you like.
What access type is used is defined by the place where you put the #id annotation. If it is on a field, field access is used. If it is on a getter/setter property access is used.
JPA spec.
The persistent state of an entity is accessed by the persistence provider
runtime either via JavaBeans style property accessors (“property
access”) or via instance variables (“field access”).
It's publically available, so if using JPA you really ought to get it, or a book/documentation that presents it.
I have a series of models, each of which has some properties that are used by a generator to generate getters/setters automatically (because there is some logic relating to default values contained therein and I don't intend to write these manually for models with 20 odd fields).
When I'm instantiating the model, I use GWT.create(...), but sometimes I have classes which refer to my model, and these don't know that the setters/getters exist, because they are generated.
For example, I have my model:
public class MyModel extends AbstractModel {
private Integer uid;
private String name;
// ...
}
public interface JsonBinder<MyModel> {
public void bindDataToMode(MyModel model, JSONWrapper json);
}
Now JsonBinder<T> is also a generated class using GWT.create, but it refers to MyModel and not the generated MyModelImpl. Therefore on compile I get errors like setUid(Integer value) is not defined for class MyModel.
Is there a way to have the compiler replace all uses of MyModel with MyModelImpl?
This applies to both generics and method arguments, return types, etc..
No.
In your specific case, I'd rather generate the MyModelImpl et al. upfront, using whichever code generator you want (including, for example, an annotation processor) and then code against the generated classes directly.
I just want to know what is the difference between all these annotations. Why are we using these... means they have no effect especially field level and property level.
And what is the purpose of using mixed level annotation like:
#Entity
#Access(AccessType.FIELD)
class Employee {
// why their is a field level access
private int id;
// whats the purpose of transient here
#Transient
private String phnnumber;
// why its a property level access
#Access(AccessType.property)
public String getPhnnumber() {
return "1234556";
}
}
what exactly this class says?
By default the access type is defined by the place where you put your mapping annotations. If you put them on the field - it will be AccessType.FIELD, if you put them on the getters - it will be AccessType.PROPERTY.
Sometimes you might want to annotate not fields but properties (e.g. because you want to have some arbitrary logic in the getter or because you prefer it that way.) In such situation you must define a getter and annotate it as AccessType.PROPERTY.
As far as I remember, if you specify either AccessType.FIELD or AccessType.PROPERTY on any of the entity fields / methods you must specify the default behaviour for the whole class. And that's why you need to have AccessType.FIELD on the class level (despite that AccessType.FIELD is the default value.)
Now, if you wouldn't have #Transient on the phnnumber field, the JPA would provide you with a 3 columns table:
id,
phnnumber,
getphnnumber.
That's because it would use AccessType.FIELD for all of the entity fields (id and phnnumber) and, at the same time, it'd use AccessType.PROPERTY for your getter (getPhnnumber()).
You'll end with phone number mapped twice in the database.
Therefore, the #Transient annotation is required - it means that the entity won't store the value of the field in the underlying storage but the value returned by your getter.
I'm borrowing the "slice" meaning from C++.
Let's say I hava a simple POJO that's persisted via Hibernate:
class Person {
private long id;
private String name;
...
// getters and setters here
...
}
Now, when I retrieve an object from the database I know it was "instrumented" by Hibernate (its real class is a Person-derived generated automatically). I want to convert it back to a "plain" person object. Tnat would be used, for instance, to submit the object to XStream and have the result containing only what Person contains.
I could do it by defining a copy constructor, but I don't want to have the hassle of having to write copy constructors for every ORM class (not to mention the violation of DRY principle).
So I was wondering if
a) is there already a Java lib that does it?
b) If not, would it be practical to write one using reflection?
In case of (b), any recomendations/guidelines/code skeletons would be appreciated.
The bean mapping library Dozer does an excellent job of this and is dead simple to use.
Simply map an instance of the bean returned by Hibernate to it's own class:
Person person = session.load(...);
BeanMapper mapper = ...;
Person cleanPerson = mapper.map(person, Person.class);
voila, no more Hibernate proxies or lazy-loaded collections!
The class org.apache.commons.beanutils.BeanUtilsBean probably does almost everything you want. The copyProperties method will go through calling the getters on your Entity and looking for setters with a matching property name on a target object you provide. You may need to handle some nested entities, depending on what kind of behavior you want and if/how you map relationships.
If you need to get more sophisticated you can register a Converter for turning your nested entity types into something else as well.
There is an interesting discussion about your problem here
http://www.mojavelinux.com/blog/archives/2006/06/hibernate_get_out_of_my_pojo/
Several solutions are proposed in the comments. In particular
http://code.google.com/p/entity-pruner/
http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/
I personally am huge on layer separation, and would argue that classes that you want to serialize across the wire or to XML should actually be separate from your data access layer classes, which would also solve the problem.
class SerializablePerson
{
... fields you care about ...
SerializablePerson(Person person)
{
... set only what you care about ...
}
}
You could have a Person class without persistence information wrapped by a persistent counterpart, like this:
public class Person implements Serializable
{
private String name;
// others.
}
public class PersistentPerson
{
private Long id;
private Person data; //
public Person getPerson() { return this.data; }
}
I'm not sure the design is worth it. The dual model makes me throw up in my mouth a little, just while writing this example.
The larger question is: Why do you think this is necessary? IF there's no good way to tell XStream to not include the id when serializing, I'd say it'd be better to write your own javax.xml.bind.Marshaller and javax.xml.bind.Unmarshaller to get what you want.
There are better ways to solve this problem than bastardizing your entire design.
Java has the transientkeyword. Why does JPA have #Transient instead of simply using the already existing java keyword?
Java's transient keyword is used to denote that a field is not to be serialized, whereas JPA's #Transient annotation is used to indicate that a field is not to be persisted in the database, i.e. their semantics are different.
Because they have different meanings. The #Transient annotation tells the JPA provider to not persist any (non-transient) attribute. The other tells the serialization framework to not serialize an attribute. You might want to have a #Transient property and still serialize it.
As others have said, #Transient is used to mark fields which shouldn't be persisted. Consider this short example:
public enum Gender { MALE, FEMALE, UNKNOWN }
#Entity
public Person {
private Gender g;
private long id;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public Gender getGender() { return g; }
public void setGender(Gender g) { this.g = g; }
#Transient
public boolean isMale() {
return Gender.MALE.equals(g);
}
#Transient
public boolean isFemale() {
return Gender.FEMALE.equals(g);
}
}
When this class is fed to the JPA, it persists the gender and id but doesn't try to persist the helper boolean methods - without #Transient the underlying system would complain that the Entity class Person is missing setMale() and setFemale() methods and thus wouldn't persist Person at all.
Purpose is different:
The transient keyword and #Transient annotation have two different purposes: one deals with serialization and one deals with persistence. As programmers, we often marry these two concepts into one, but this is not accurate in general. Persistence refers to the characteristic of state that outlives the process that created it. Serialization in Java refers to the process of encoding/decoding an object's state as a byte stream.
The transient keyword is a stronger condition than #Transient:
If a field uses the transient keyword, that field will not be serialized when the object is converted to a byte stream. Furthermore, since JPA treats fields marked with the transient keyword as having the #Transient annotation, the field will not be persisted by JPA either.
On the other hand, fields annotated #Transient alone will be converted to a byte stream when the object is serialized, but it will not be persisted by JPA. Therefore, the transient keyword is a stronger condition than the #Transient annotation.
Example
This begs the question: Why would anyone want to serialize a field that is not persisted to the application's database?
The reality is that serialization is used for more than just persistence. In an Enterprise Java application there needs to be a mechanism to exchange objects between distributed components; serialization provides a common communication protocol to handle this. Thus, a field may hold critical information for the purpose of inter-component communication; but that same field may have no value from a persistence perspective.
For example, suppose an optimization algorithm is run on a server, and suppose this algorithm takes several hours to complete. To a client, having the most up-to-date set of solutions is important. So, a client can subscribe to the server and receive periodic updates during the algorithm's execution phase. These updates are provided using the ProgressReport object:
#Entity
public class ProgressReport implements Serializable{
private static final long serialVersionUID = 1L;
#Transient
long estimatedMinutesRemaining;
String statusMessage;
Solution currentBestSolution;
}
The Solution class might look like this:
#Entity
public class Solution implements Serializable{
private static final long serialVersionUID = 1L;
double[][] dataArray;
Properties properties;
}
The server persists each ProgressReport to its database. The server does not care to persist estimatedMinutesRemaining, but the client certainly cares about this information. Therefore, the estimatedMinutesRemaining is annotated using #Transient. When the final Solution is located by the algorithm, it is persisted by JPA directly without using a ProgressReport.
If you just want a field won't get persisted, both transient and #Transient work. But the question is why #Transient since transient already exists.
Because #Transient field will still get serialized!
Suppose you create a entity, doing some CPU-consuming calculation to get a result and this result will not save in database. But you want to sent the entity to other Java applications to use by JMS, then you should use #Transient, not the JavaSE keyword transient. So the receivers running on other VMs can save their time to re-calculate again.
In laymen's terms, if you use the #Transient annotation on an attribute of an entity: this attribute will be singled out and will not be saved to the database. The rest of the attributes of the object within the entity will still be saved.
Im saving the Object to the database using the jpa repository built in save method as so:
userRoleJoinRepository.save(user2);
For Kotlin developers, remember the Java transient keyword becomes the built-in Kotlin #Transient annotation. Therefore, make sure you have the JPA import if you're using JPA #Transient in your entity:
import javax.persistence.Transient
I will try to answer the question of "why".
Imagine a situation where you have a huge database with a lot of columns in a table, and your project/system uses tools to generate entities from database. (Hibernate has those, etc...)
Now, suppose that by your business logic you need a particular field NOT to be persisted. You have to "configure" your entity in a particular way.
While Transient keyword works on an object - as it behaves within a java language, the #Transient only designed to answer the tasks that pertains only to persistence tasks.