So I am aware that Spring automatically maps complex objects correctly when provided like:
#PostMapping("/foo")
public String insertObject(#ModelAttribute MyComplexObject bar) {
//do something
return "redirect:baz";
}
given that MyComplexObject has "mappable" attributes, for instance something similar to:
public class MyComplexObject {
private long id;
private String name;
public MyComplexObject(long id, String name) {
this.id = id;
this.name = name;
}
// setters & getters etc
}
However, what if the required object in turn has other complex objects as attributes, e.g. MyComplexObject keeps a list of MyOtherObject which again could reference another one and so on.
A possible solution I found was creating a form object for the required class which translates all attributes to mappable types, but even then it'd be rather tedious and messy depending on complexity.
Every suggestion is much appreciated!
Related
public enum CameraType {
CAMERA(false, false, "External lens ", ""),
CameraType{
boolean collector,
boolean hidden,
String description
) {
this.collector = collector;
this.granular = hidden;
this.description = description;
} // end ctor
public void setHide(boolean hidden) {
this.hide = hidden;
}
} // end enum
I have few Instance of CameraType.
I have a setter for "hidden" property which on certain condition is set to true or false.
Now I serialize CameraType with few other fields inside SecurityEntity.
```
#Entity
#Table
public class Security {
Few more fields...
#Enumerated(EnumType.STRING)
#Column(nullable = false)
private CameraType cameraType
And other fields...
}
```
When I deserialize the value of "hidden" field is always false. If I understand correctly, during deserialization ctor is called and default is assigned.
Is there a way I can retain the value of "hidden" field(true or false) after deserialization per instance of CameraType.
I am using Postgres DB 10.
enter code here
Please Please help. I am out of clues.
By definition, enums are immutable elements of a fixed set. Because of this, to represent an enum value you just need its name. That's exactly what JPA does during serialization/deserialization.
You are trying to violate the rules. While Java allows you to treat enums almost as plain objects, JPA treats them according to what they are supposed to be. That's why your code is not working.
You can either:
make CameraType into a class and serialize it as such, or
split CameraType into two parts, for example enum CameraType (immutable) and class CameraConfig (with all the mutable fields)
The former answer is correct : enums must be immutable and dividing parts into immutable and mutable data is a good choice.
One addition here: using the enum values for database storage is often not a good choice, because when another developer decides to refactor the enum names and you are after this reading old entries from database, you got a crashing application...
So I would suggest to use javax.persistence.AttributeConverter to deserialize/serialize an enum in a specific and rename save way.
Here a very simple example with an enum called MyDefinition:
enum MyDefinition{
ONE("def_one"),
TWO"def_two"),
THREE("def_three"),
;
private String id;
private MyDefinition(String id){
this.id=id;
}
public String getId(){
return id;
}
public static MyDefinition fromId(String id) {
for (MyDefinition definition : MyDefinition.values()) {
if (definition.id.equals(id)) {
return definition;
}
}
return null;
}
}
Here the converter:
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
#Converter(autoApply = true)
public class MyDefinitionAttributeConverter implements AttributeConverter<MyDefinition, String> {
#Override
public String convertToDatabaseColumn(MyDefinition attribute) {
if (attribute == null){
return null;}
}
return attribute.getId();
}
#Override
public MyDefinition convertToEntityAttribute(String dbData) {
return MyDefinition.fromId(dbData);
}
So we can use the ids for database. A renaming of the enum names will no longer lead to a crashing application when reading old data.
The nested builder patterns that I've come across online usually have something like this:
class Person{
private int id;
private String name;
private int age;
... so on
private Person(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
}
public static class Builder{
private int id;
private String name;
private int age;
... so on
public Builder id(int id){
this.id = id;
return this;
}
public Builder name(String name){
this.name = name;
return this;
}
.... so on
public Person build(){
return new Person(this);
}
}
}
My question is, is it necessary to duplicate fields in Person and Builder? It seems like a lot of redundant code. And my second question is, would the following code be a viable replacement, why or why not?
class Person{
private int id;
private String name;
private int age;
... so on
private Person(){}
public static class Builder{
private Person person = new Person();
public Builder id(int id){
this.person.id = id;
return this;
}
public Builder name(String name){
this.person.name = name;
return this;
}
.... so on
public Person build(){
return person;
}
// UPDATED -- another build method
public Person build(){
Person built = this.person;
this.person = new Person();
return built;
}
}
}
Note: I understand this topic may be opinionated and there may not be a "right" answer, but I just want to hear different ideas and opinions. I'm not looking for the ultimate truth.
Your code would be fine as long as:
you keep your Person member variables private (you are doing so)
you don't provide methods that allow modification of those member variables (the code you show does not do, but you have omitted parts of it)
those member variables are immutable or you ensure getters provide copies of them. usually better that the members are already immutable (hint: even java collections). otherwise you will be creating instances on each getX call.
once Builder.build is called, noone must be able to modify Person instance state, not even Builder itself. this is not happening in the code you posted
builder does not expose "temporal instance" being built (if any at all). No instance must be exposed aside the return of build method.
there are opinions about which is the preferred way or not, matter of taste most of the time. But in terms of being right or not, that approach would be fine with some modifications. At the end, what happens before the build is called is purely internal to the Builder. It's an implementation matter. The important thing is that the previous rules are met.
To fix rule 4: your Builder.build method should return a deep clone of the temp instance being used (there are ways to achcieve that without needing to specify each field). Or, you should have a flag in builder that forbids calling any other method on Builder instance, once build has been called.
Side note: i usually prefer that Builder class also uses private constructor. I would have this on Person class:
public static Builder builder() {
return new Builder();
}
This can give you more flexibility on the way to initialize the Builder, or even you can have several builder methods doing not exactly the same stuff in terms of "preconfiguring" the builder (and since they are methods, you have more flexibility on naming than on constructors :) )
Please look at the code below
Class Employee{
private String name;
private String id;
public String getName(){ return name; }
public void setName(String name){ this.name = name; }
public String getId(){ return id; }
public void setId(String id){ this.id = id; }
}
Class Teacher extends Employee{
private double salary;
}
Now my question is If I am creating an object of Teacher , then it does not make sense without the Teacher object having a name and id. I can set the same for teacher object via public setters of Employee but it it correct ?
Teacher t1 = new Teacher();
t1.setName("aaa");
t1.setId("224");
t1.salary = 200.00;
System.out.println(t1.toString());
I am asking this question as my understanding is if the field is private it should be used only via getters . But in the example provided above Teacher object will not make sense without having a Name or Id .
If it is correct then why not make the field public in the first place? What is the advantage in using it private and then allowing access via public setter ?
If it is not correct please provide an example of how the above Employee and Teacher class should be implemented ?
Your question seem to show a confusion between two concepts rather independant:
encapsulation
creation of objects
Encapsulation: it is better design to define private variables. Then you can not corrupt the object from outside. You must use setter to modify your employee.
But, if you trust Teacher, it could modify Employee as a subclass, without setter, it is faster to code (but little risky: if you have to change the setter in employee, Teacher wont get it, ...).
Creation of objects: you should pass certain values to the variables, or they are defined by default (or auto-built ...)
=> you can decide that Teacher have well defined values (default), or that you must give these values (mandatory). It is your design.
After that, you can change them directly or by setters of Employee (=> first concept of encapsulation).
then it does not make sense without the Teacher object having a name and id. I can set the same for teacher object via public setters of Employee but it it correct ?
This is where exactly constructor comes into picture. You need to pass them before you are using it.
Thumbrule : When you want something while building it, you need to force them to pass on constructor.
class SomeClass{
List<Someclass> list=new ArrayList<SomeClass>();//getter and setters
}
In above class, i have created the List object of same class objects. I want to know the impact of above code and if it is ok to have, I have doubt about its recursion impact ?
The definition of List<T> is not dependent on the structure of T. The information is used by the compiler to only allow adding objects of type T and when you retrieve it automatically convert the return value to the appropriate type. So it is fine to have the List definition in the same class.
The list only contains references to objects of type T. If the complete object were to be allocated and stored as part of the list it would have caused problems.
There is a subtle problem that can cause baffling errors if you do the wrong thing, however. Suppose you try to design a class so it keeps track of all objects in that class:
public class Book {
private static final List<Book> LIBRARY = new ArrayList<>();
private String dewey;
private String isbn;
private String author;
private String title;
public Book(String dewey, String isbn, String author, String title) {
this.dewey = dewey;
this.isbn = isbn;
this.author = author;
this.title = title;
LIBRARY.add(this);
}
public static final List<Book> getLibrary() {
return LIBRARY;
}
}
This class is dangerous, as it allows a reference to this to escape the object before the constructor completes.
The compiler is allowed to reorder the statements in the constructor as it wishes, since they are all independent.
Somebody could have grabbed a copy of LIBRARY before you call the constructor, and a getLibrary call may get access to LIBRARY before the Book object is fully usable. Anything can happen then.
Also, the Composite pattern is similar to your idea.
Yes you can do it no problem.
There is no recursion problem because none of your class instances are created when the List is created - using your class name is only the type of the List.
simply use....
class SimpleClass
{
String var1;
int var2;
double var3;
}
implement all getter and setter for these variable so its will become a datatype for your list object.
now for storing object of this class use SimpleClassMgr
class SimpleClassMgr
{
//this is your list where you will store object
List<Someclass> list=new ArrayList<SomeClass>();
make methods for add().delete(),update(),get() to insert and alter your records
for example
public void add()
{
list.add(simpleclassobject);
}
}
This will create a tree of SomeClass objects. As long as you are OK with having leafs with empty lists it is no problem. You might want to look into having null instead of the list for better memory efficiency.
This is not the first time that I've found myself in a situation in which I have to adapt two objects with almost the same data, for example:
User.java (Object returned from another library)
private String name;
private String surname;
private String email;
private String telephone;
...
getters and setters();
constructor();
MyUser.java
private String name;
private String surname;
private String email;
private String telephone;
...
getters and setters();
constructor();
I usually create a method to convert one object into another one, like this:
User m1 = new User();
MyUser m2 = new MyUser();
m2.setName(m1.getName());
m2.setsurmame(m1.getsurname());
...and so on...
Does anybody know a different way to do this kind of stuff?
Use Object Composition For objects that you create using the other library, create an instance of ExternalUser. But if you want to create them locally, create a BrandNewUser. Then you can just treat them the same way, with one version using the pass-through composition methods, and the ones created by your code using your own internal implementation.
You can create your object like this:
public interface MyUser {
// all the methods you need
String getSurname();
}
public class ExternalUser implements MyUser {
private User _user;
private ExternalUser() { }
public ExternalUser(User u) {
this._user = u;
}
public String getSurname() {
return _user.getSurname();
}
}
public class BrandNewUser implements MyUser {
private String _surname;
public ExternalUser(String name, String surname) {
this._surname = surname;
}
public String getSurname() {
return _surname;
}
}
There is a AutoMapper project in C Sharp.
In the gist of it it provides an easy way of mapping properties from a source instance to a destination instance where the source and destination instances can be of different classes.
this link shares some interesting thoughts about similar projects in Java : Automapper for Java
One thing you can do is pass that User object in a method of MyUser class or constructor of MyUser class and then perform those setters.
Using constructor :
public MyUser(User u){
setName(u.getName());
setSurname(u.getSurname());
...
}
Or creating a seperate method :
public void setMyUser(User u){
setName(u.getName());
setSurname(u.getSurname());
...
}
Then you can use it like this:
User u = new User();
//hope all values are set in User u object
MyUser m = new MyUser(u);
In cases where appropriate, refactor those objects to inherit from each other, rather than duplicate properties and logic.
In cases where the objects must remain distint, you can use any one of a variety of clone tools to perform deep copies from object to object. Here is a decent, non-exhaustive list:
Orika
Dozer
PropertyUtils
Maybe you can use beanutils which provides copy properties function.
http://commons.apache.org/beanutils/