Is it possible to serialize a set of enums without a custom attribute converter?
#Entity
public class SomeEntity {
#Id
#GeneratedValue
private Integer id;
private Set<DayOfWeek> days;
}
The set of days has to be at the same table as SomeEntity.
I'm using Spring Data JPA 1.9 with Hibernate 4.3.1.
Thanks.
Hibernates stores all properties that declare a type that implements Serializable.
But the type of your days property is a Set, which does not extend Serializable. To store your set as serialized value you will need to declare a set class which implements Serializable - like most do. For example HashSet:
#Entity
public class SomeEntity {
private HashSet<DayOfWeek> days;
}
You don't need any further annotations. This works for Enum and all other serializable elements.
But for a set of enums exists another option: Use an EnumSet, which stores the values into an integer column (every enum value is exactly one bit). See my answer here: JPA map collection of Enums
Enum has Serializable as a Superinterface (see Javadoc API documentation for Enum)
So it shouldn't have any specific issue with Hibernate (which doesn't require to be serializable) or Spring Data JPA.
Related
When writing documents to Mongodb using Morphia, a structure like this will be written without any problems, and without needing the #Embedded annotation:
#Entity
public class Blog {
#Id
private String id;
private List<Comment> comments;
}
The comments field is happily stored as an array of nested Comment elements (Comment is a plain POJO with no annotations).
However, the Morphia documentation suggests I should be using this:
#Entity
public class Blog {
#Id
private String id;
#Embedded
private List<Comment> comments;
}
But in my tests using the #Embedded annotation doesn't appear to do anything additional over simply writing the structure without the annotation.
So what does the #Embedded annotation actually do? Does it affect the ability to query, or index, or some other function of storage other than simply writing the data?
Serializable is not generally used with Morphia. #Embedded is a bit of an ambiguous item whose original intent seems to have gotten lost. In fact, in my fork which I'm working on making the official 2.0 of Morphia, I've restricted it such that it only applies at the class level. This tells Morphia to map the type but not fail the mapping on a missing #Id annotation. In that branch if you wish to specify a name other than the field name, you'd simply use #Property as you would for any non-embedded types.
I hope this clarifies it a little bit at least.
As a rule of thumb, you should #Embedded for objects that are dependent on the parent object (and therefore have no life outside it), and are not shared between objects.
By default, Morphia uses the field name as the value name in Mongo. This can be overridden by specifying a name on the #Embedded annotation:
#Embedded("blog_comments")
private List<Comment> comments;
Even without #Embedded you can still use java class as field type as long as that class implements java.io.Serializable. However that field will be stored in MongoDB in binary format instead of structured data as shown above.
Sources here and here
I am using #Convert(converter = CoverConverter.class) to convert attribute value before storing it on a database and vice versa. I have to declare this annotation at each an every place where I am using a particular ENUM. Let's call it TestENUM for now.
But this particular ENUM is used at more than 100 places and I am not sure that other developers in my group will remember to add this annotation when they use this ENUM.
So I was wondering if there was a way that I can annotate an ENUM directly in a way that wherever it is used it will be converted before being persisted into database and vice versa when fetched from database through JPA
so example:
#Convert(convert = true)
public enum TestENUM {}
You should be able to create a Converter and use the autoApply property:
If the autoApply element is specified as true, the persistence
provider must automatically apply the converter to all mapped
attributes of the specified target type for all entities in the
persistence unit except for attributes for which conversion is
overridden by means of the Convert annotation (or XML equivalent).
http://docs.oracle.com/javaee/7/api/index.html?javax/persistence/Convert.html
#Converter(autoApply = true)
public class MyEnumConverter implements Converter{
}
Using Hibernate with MySQL, I like to use same class and store in two different table. How can i map one class with multiple tables?
I came across this thread,
hibernate two tables per one entity
which gives a suggestion to use two different Identity Name for same class through XML configuration. Can some one give me pointers how should i do this mapping in Java configuration? Or can it be done using annotation?
example,
There is Student Class
#Entity
#Table(name="Student_1")
public class Student{
#Id
private int StudentId;
private int StudentName;
private int studentMailId;
}
I like to have similar Table with same fields with the table name as Student_2. How should I annotate and use it to save in different tables?
I know this question was asked long time ago, and a response was posted here .
I would like to suggest an alternative way, without using any of hibernate things.
Declare an interface with getter and setter methods of commun columns, then make your Student_1 class and Student_2 classs implement this interface.
Leave your JPA mapping in this two class as usual, then in your code, you can invoke method of this interface instead.
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.
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.