I have this Entity, that is a super class:
#Entity
public class Father implements Serializable{
#Column(name = "name")
#Size(min=1, max=10)
#Pattern(regexp="^[A-Za-z ]*$")
#NotNull
private String name;
}
this one, extends the one above:
#Entity
public class FatherSub extends Father implements Serializable{
private String name;
}
As you can see, in FatherSub I don't have #Annotations and I don't want them.
How can I override them? Is there a way?
It seems that the annotations #NotNull persist in the subclass and ask me to fill
Father.name (not FatherSub.name) as you can see in these 2 Eclipse printscreen pics.
Thank you
Annotations, which just represent some meta info for some specific period of time, are not over-writable when having a subclass. So it's up to the implementation how annotation inheritance is implemented. For the Validator Framework, annotations scattered over multiple inherited classes are aggregated.
In your example, the FatherSub#name member hides the Father#name member. This means that all instances of FatherSub will work with the name defined in FatherSub. But because the Validation implementation takes also inherited annotations into account, though the FatherSub#name does not have a #Column annotation, the error pops up. You can't change this behaviour, so you must choose to either not use inheritance at all or give the child class the validator annotations instead of the parent.
Additionally, you don't need to explicitly implement Serializable in FatherSub, as Father already implements it.
Related
I need to implement entity property lazy loading. I came with single table inheritance approach.
#Entity
#Table(name = "person")
#Getter
public class Person {
#Id
#GeneratedValue(strategy = IDENTITY)
private Long id;
#Column(name = "firstname")
private String firstName;
}
#Entity
#Getter
public class VerbosePerson extends Person {
#Column(name = "lastname")
private String lastName;
}
public interface PersonRepository extends JpaRepository<Person, Long> {}
public interface VerbosePersonRepository extends JpaRepository<VerbosePerson, Long> {}
Unfortunately, this only works with a discriminator column. Actually, I don't need to distinguish these two entities. All that requires is to exclude lastName column from the Person fetching and to load it only when VerbosePerson is being requested.
One solution is to declare #MappedSuperClass that should have two inherited entities (Person and VerbosePerson). But in this case, Person won't be a supertype for VerbosePerson which is not convenient.
Is there any way to use single table strategy inheritance without discriminators?
It sounds like you need lazy querying and not the inheritance. You should take a look at FetchType annotations
https://thorben-janssen.com/entity-mappings-introduction-jpa-fetchtypes/
Be warned though.. these are primarily used to manage lazy loading for Lists (things that can be easily proxied). Lazily associating a single item (i.e. a #ManyToOne or a simple string, etc.) usually requires some careful object proxying under the covers to ensure it works the way you think it should in your persistence framework. Generally I didn't use it much but I think I did at one point or another to lazily load a class that had variables mapped to a row of a hibernate object that I lazily loaded..
Check out:
https://thorben-janssen.com/lazy-load-non-relational-attributes/#:~:text=The%20JPA%20specification%20defines%20the,value%20must%20be%20eagerly%20fetched.
Pay special attention to the parts:
practices, that means that depending on your JPA implementation, annotating an attribute with #Basic(fetch=FetchType.LAZY) isn’t enough.
Lazy loading for fields requires bytecode enhancement. Then you can use #Basic(fetch = LAZY) and the field will be lazy loaded on first access. Also see https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#BytecodeEnhancement
The hibernate POJO only allow list, which is an interface, to map many-to-one relationship.
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
private List certificates;
But GWT-RPC only allows concrete type, such as ArrayList, as the return.
So, instead of defining a similar class with ArrayList only for RPC,
public class EmployeeRPC {
private int id;
private String firstName;
private String lastName;
private int salary;
private **ArrayList<Certificate>** certificates;
is there any other way to convert the hibernate POJO into a serializable object?
Thanks
You can use List<Serializable> but the generated javascript will be bigger.
When passing objects across RPC call's its a good practice to declare concrete parameter types in the RPC interface. If for some reason you cannot use concrete class in the RPC interface try to be as specific as possible.
This is because the GWT compiler while emitting javascript has to take into account all possible variants of List in the compilation unit. This includes all the classes extending List and Serializable interface in the class path. The permutations can be huge, which will effect your compile time as well as the application download size.
Full answer here
Making a class serializable for GWT RPC:
A class is serializable if it meets these three requirements:
- It implements either Java Serializable or GWT IsSerializable interface, either directly, or because it derives from a superclass that does.
- Its non-final, non-transient instance fields are themselves serializable, and
- It has a default (zero argument) constructor with any access modifier (e.g. private Foo(){} will work)
Docu
You will have to add this stuff to your class...
Also make sure that Certificate is serializable.
Or just use JSON: resty-gwt, gwt-jackson
I have some beans that I annotated with JPA to handle persistence mapping.
Here is an example:
import javax.persistence.Id;
public class User{
#Id
private String id;
public String getId(){
return id;
}
public void setId(String id){
this.id = id;
}
}
Now I want to use this class in another project where I don't need a dependency on javax.persistence, so I'd rather not include it just for such classes.
So I was thinking of splitting this bean in two classes: one with just fields and accessors and a subclass with JPA annotations on accessors. Like:
public class User{
private String id;
public String getId(){
return id;
}
public void setId(String id){
this.id = id;
}
}
and
import javax.persistence.Id;
public class UserEntity extends User{
#Override
#Id
public String getId(){
return super.getId();
}
}
Unfortunately it seems that putting JPA annotations on accessors is a discouraged practice in most cases and I second that.
Can you suggest any cleaner solutions?
This may not be helpful if you absolutely have to use the annotation-based mapping for JPA, but if you are open to it you could configure your mappings using xml and not include the xml mapping file in the jar you use to share the User class with other projects.
See example here:
Persisting Entity Classes using XML in JPA
If you insist on using annotations to define your entity mappings, then your entity classes cannot avoid being dependent on JPA. If you must present non-JPA-dependent classes representing the same data, and if you want to be able to handle the different representations polymorphically, then your options are limited:
the annotated class may extend the non-annotated one, or
the annotated and non-annotated classes may extend a common superclass, or
the annotated and non-annotated classes may implement a common interface.
In any of those cases, the entity class can provide its own, annotated, member variables for the entity properties, but in all cases, doing so means the two classes provide separate storage for the entity properties. That's a bit wasteful in the first alternative and possibly in the second, but it's the only way you can annotate the member variables without tying the whole hierarchy to JPA.
If you want to go in this general direction then I'd recommend using interfaces instead of class inheritance, whether you annotate member variables or accessor methods. Using interfaces for polymorphism better models the reality you describe (some Users are entities but others are not), it does not interfere with any inheritance hierarchy you may want, and if you annotate member variables then it avoids duplicative storage .
For example, I have entity class User:
public class User
{
private long id;
private String name;
// setters and getters
}
Next, I add new entity class: Comment
public class Comment
{
private long id;
private String comment;
// setters and getters
}
Next, I can add more and more entity classes.
And, at this moment I think: I can/must bind/connect in logical structure my entity classes or no?
What I mean? I try explain:
Point 1: All this classes: User, Comment and more other - POJO.
Idea 1: Need logical binding for this classes via interface or abstract class.
Point 2: I see, that All entity classes has same methods: getId and setId().
Idea 2: Need to avoid declaration this methods in all classes.
My Solution:
Add interface BaseEntity:
public interface BaseEntity
{
public long getId();
public void setId(long id);
}
Add all entity classes must implement this interface.
In result we logical connect all entity classes. And we guarante that each entity class implement getId() and setId() methods.
But this solution doesn't resolve problem with multiple declaration getId and setId.
A solution is to create general BaseEntity class:
public class BaseEntity
{
private long id;
public long getId() {return this.id};
public void setId(long id) {this.id = id;};
}
And all entity class must extends BaseEntity class.
mmmm, sound nice :)
But, with current implementation - user can create instanse BaseEntityClass. This make sense? I can give possibility to create a class BaseEntity?
Or maybe, good solution mark this class as abstract?
What do you think?
And if you agree with all my previous steps:
I have last question:
Communication beetween classes must based on Interfaces. But I dont have interface for entities. It is can create problems for me in future?
Thank you.
Yes, make your base entity an abstract class and let other extend it.
public abstract class BaseEntity
{
private long id;
public long getId() {return this.id};
public void setId(long id) {this.id = id;};
}
As a general rule, one should always program to an interface and not to an implementation.
You could use an abstract BaseEntity class, mapped with #MappedSuperclass. But you still would have to override the mapping of the ID field to the appropriate column in every subclass.
Just because two classes have the same property doesn't necessarily mean that they should extend a common class. Your code will probably never reference any object with the type BaseEntity. Unless you have additional common methods, I would advise not to use a superclass in this case. It will just be simpler.
And entities are POJOs. Using an interface for every entity, in my experience, just adds unnecessary complexity.
Making BaseEntity abstract is perfectly good, I have used it myself this way. And I don't think there's anything else you can abstract. You could abstract if you would have multiple tables that all have some common columns, such as for auditing purposes.
And interfaces for entities? I don't think that's anything useful. Interfacing is more useful when you have to switch different implementations, now in entities, that doesn't make much sense.
This question already has answers here:
When should we implement Serializable interface?
(3 answers)
Closed 6 years ago.
#Entity
public class Husband implements Serializable {
#Id
private int id;
private String name;
#OneToOne
private Wife wife;
}
#Entity
public class Wife implements Serializable {
#Id
private int id;
private String name;
#OneToOne(mappedBy="wife")
private Husband husband;
}
What is Serializable in broad term?
Why does a class implements Serializable interface?
Why does the husband member alone have #OnetoOne(mappedBy ="Wife"), but the wife member does not have #OnetoOne(mappedBy="husband")
Serialization, in broad terms, is the way Java provides developers to persist the state of any object to a persistent store.
If a developer wants that for some reason instance of his coded class should be persisted to a backing store, then the class needs to be declared as implementing Serializable.
The above code represents a One to One relationship between a Husband and a Wife. Which basically means that each wife is related to one husband and each husband is related to one wife. :-) Also in the above relationship, the Husband is the master of the relationship [in Entity-Relationship terms] and that is why Wife says that it is mapped/associated to Husband by the Husband and not the other way around. Which means Husband identifies its wife and not the other way around.
1) The Serializable interface is just a marker. It means that objects can be serialized, i.e. they can be represented as a bit string and restored from that bit string.
For example, both of your classes are serializable because they can be represented as a bit string (or regular string). On the other hand, a class that represents a file handle given out by the operating system can not be serialized: As soon as the program is finished, that handle is gone, and there is no way to get it back. Reopening the file by file name is not guaranteed to work, since it may have been deleted/moved/changed permissions in the meantime.
2) Serializing objects that don't implement the Serializable interface will result in a NotSerializableException being thrown.
3) According to the documentation:
mappedBy
This element is only specified on the inverse (non-owning) side of the association.
The interface Serializable helps to persist the state of an object instance.
According to the jpa specification:
"If an entity instance is to be passed by value as a detached object (e.g., through a remote interface), the entity class must implement the Serializable interface" - JSR 220 Persistence - see 2.1 Requirements on the Entity Class
According to the java ee documentation:
"The field that owns the relationship. This element is only specified on the inverse (non-owning) side of the association." - Java EE 6 Documentation
I just want to answer the third question because it's not fully explained.
Here is your question:
Why does the husband member alone have #OnetoOne(mappedBy="Wife"), but the wife member does not have #OnetoOne(mappedBy="husband")
First, there is something wrong here: it should be:
#OneToOne(mappedBy="wife"), not Wife. Note that mappedBy should be followed by the attribute wife of the Husband class, not the class Wife, neither the Husband class name, although the Husband class is the owner. In the document of Hibernate is said:
mappedBy refers to the property name of the association on the owner side.
Second, one thing to have in mind is, there are two kinds of relationship when we do the database mapping: unidirectional and bidirectional. We use unidirectional relationship, when we only want one part handle/maintain this relationship, but from the other side, we are not interested in getting the data of this side. In your example, if we just want an unidirectional relationship from Husband to Wife class, we only want to know, by having an object of type Husband, who is his wife(by its getWife() method), but we are not interested in knowing one lady's husband.
Under this circumstance, we can code like this:
(note that in class Husband we have attribute of Wife type, but in Wife class we don't have attribute of Husband type)
Husband.java:
#Entity
public class Husband implements Serializable {
...
#OneToOne
//note that #JoinColumn is necessary when mapping,
//and although in the table you may have columns like
//`ID_WIFE` in table of Husband, in Java it's not a number
//attribute, it's an attribute of `Wife` type.
#JoinColumn(name="idWife")
private Wife wife;
}
Wife.java:
#Entity
public class Wife implements Serializable {
#Id
private int id;
private String name;
//We can omit the attribute `husband` of `Husband` type,
//because we are not interested in it. Or, we don't need
//to map in the owned side, because it's unidirectional.
}
But, if we want to have an bidirectional relationship, we have to map in both side and in the owned side, mappedBy is needed before the attribute owned.
We remain the Husband side intact, and we change the Wife.java:
Wife.java:
#Entity
public class Wife implements Serializable {
#Id
private int id;
private String name;
#OneToOne(fetch=FetchType.LAZY, mappedBy="wife")
private Husband husband;
}
Check this page: https://en.wikibooks.org/wiki/Java_Persistence/OneToOne, it explains it all in an understandable way.
Third, just a little note: the owner side, is commonly the class of a table with a FK of another table. Or, we just remember: the owner owns it all, so it also has the FK in its table.