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.
Related
I have a class with a variable with validation annotation:
import javax.validation.constraints.NotNull;
public class Class_A {
#NotNull
private String name;
public getName() {
return name;
}
}
This class is used in a function:
public void myFunction(Class_A aObj) {
System.out.println(aObj.getName());
}
But now, I want to conditionally use the validation. I have searched and found that there is no way to conditionally check for the validation so I figured I will have to split the Class_A into two classes, one with validation (Class_A_Val) and one without validation (Class_A_NoVal).
By doing that, I can only think of below solutions for myFunction:
1) Duplicate myFunction, one for each class (Code duplication)
2) Create an abstract class with abstract method getName() and make other two classes inherit this abstract class so I can call myFunction(Abstract_Class_A)
3) Create an interface with method getName() and make other two classes implement this interface so I can call myFunction(Interface_Class_A)
Which is considered to be the best way and why? I am leaning towards #2.
Is there any other way to implement this?
Is there a way to annotate an inherited variable?
You can override the annotations by using xml configuration. More information here.
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.
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 .
Some java classes need to have private properties with a public getter and setter in order to function properly. For example JSF beans and JPA entities need them. If it wasn't for those libraries, there are probably some properties which should not have any getters and definitely not setters. Also empty constructors are oftenly discouraged for use by custom code. For example
#Entity
public class MyEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public MyEntity() {}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
}
In this class the method setId should never be called by manual code. The method is not deprecated though, so an #Deprecated annotation would be wrong.
Is there another way than #Deprecated to tell a method should not be used?
JPA entities don't need public getters and setters. Values are set using reflection (at least when using EclipseLink or Hibernate which you're probably using).
In this particular example you could simply leave the setter out, I have made a habit out of it and never had a problem with it. Note: Stick to Java naming conventions when it comes to properties and getters/setters. Some libraries/frameworks (wrongly imo) depend on this.
As for the global concept of the question, I am surprised I didn't see a suggestion that includes documentation. Documentation has, is, and will probably always be your greatest communication to users of your code.
/**
* WARNING! DO NOT USE THIS UNLESS YOU ARE GOD!
* This will probably break stuff unless...
* ....
*/
public void doEvilHackishThings()
{
// Stuff happens here.
}
If you document your code properly, developers know when they're likely to break stuff. Make sure you don't apply voodoo code etc. Good documentation describes in some detail what it does and how it does it. No developer in his right mind will touch the example method without understanding why it is evil.
You could hide getters and setters by using an interface that is backed by that concrete class. This would also encourage Tell, don't ask, because there aren't any getters you could use on the interface. The constructor usage can also be hidden in factories.
I have some Entities that look like this:
#Entity
public abstract class AbstractEntity{
#Id
private Long id;
String name;
User author;
#Lob
byte[] data;
}
public class EntityOne extends AbstractEntity{
// nothing new
}
public class EntityTwo extends AbstractEntity{
// nothing new
}
public class EntityThree extends AbstractEntity{
// nothing new
}
The byte[] defined in the superclass is the interesting part of each subclass entity. The reason I want to subclass is to enforce typing rules, as some parts of the program require EntityThree, while some parts of the program require EntityTwo. the byte[] will have completely different meaning from subclass to subclass.
It feels a little strange, because I don't expect that any of the subclasses will add any fields or methods... So i use inheritance only as a typing tool.
Is this a reasonable design? A better way to accomplish this? Does it break any best practices?
It is a good OO practice. For the database, use the SINGLE_TABLE Inheritance strategy (the default), and maybe use a custom #DiscriminatorValue per subclass, otherwise you'll get classnames in your table.
From a DBA perspective, there is no difference between this and using a single class with a property TYPE.
For OO, the subclasses can be much more usefull, e.g. you can use it to implement certain methods differently or implement the visitor or strategy pattern instead of tedious if-then-else or instanceof structures.
It's hard to say without knowing the exact use-case, but it looks like you just want to reuse the common fields in all the entities, but that no other entity will have references to AbstractEntity - only to one specific subclass. In this case, you should map the superclass with #MappedSuperclass rather than with #Entity. Each entity will have its own table, and can override the mapping defined in the mapped superclass.
Note that if I'm mistaken, and you really need an entity inheritance, using instanceof, at least with Hibernate, will cause problems, because you might have a proxy to the base class, which doesn't know yet the exact subclass the foreign key is pointing to, and which is thus not an instance of any of the subclasses.