Deep copy between different class name with same fields + Java - java

I have two objects with name Site and AppSite, both has same fields like below. Is there any util class to copy all the fields from AppSite to Site, like BeanUtils.copyProperties.
public class AmsSite implements Serializable{
private long siteId;
private String name;
private String routingId;
private String siteType;
private List<AmsPlatform> platforms;
private List<AmsProvider> providers;
public class Site implements Serializable{
private long siteId;
private String name;
private String routingId;
private String siteType;
private List<Platform> platforms;
private List<Provider> providers;
If you see in above two pojo, i have two list of object fields. Both that object also same like Site and AmsSite object only. Has same field name but different class name.
BeanUtils.copyProperties is copying all the literal field values from AppSite to Site properly, but not the inner object. (I mean deep copy is not happening). I saw Serialization.clone in apache common lang works for deep copy, but that works only if we have same class name. My case is bit different same field name but different class name.

You could try an object mapper like Orika but I'm not sure if it will work with inner classes.
If you have a lot of these type of objects you might want to consider restructuring your objects to fit an easier pattern.

Related

Question about Springboot, mongoDB relations and API

So I'm trying to create a project based in some weather forecast API and the data comes in different objects like:
public class WeatherForecast{
private String local;
private int maxTemp;
private int minTemp;
private int precipitationId;
}
public class Precipitation{
#Id
private int id;
private String descriptionEn;
private String descriptionCh;
...
}
So, I want to store this information and obtain the description of the Precipitation in the language that I desire, without receiving an WeatherForecast with the description of 10+ languages.
I searched a lot about defining relations between the tables but I couldn't find something related to relationships by id's. I found that I could use,
#DbRef
private Precipitation precipitation;
but I couldn't understand how it can interpret the Id without passing in the constructor.
And, finally, I want to understand if it's a good practice to send the two objects
separately to the database and try to workout some functionality to get the object I want, something like this:
public class WeatherForecast{
private String local;
private int maxTemp;
private int minTemp;
private String description;
}
using criteria, queries, or other things without extracting the two tables and searching in Precipitations for the desired description language.

MongoDB map Java POJO without org.bson.types.ObjectId

I want to map Java POJO to MongoDB and implement CRUD operations. I follow manual https://mongodb.github.io/mongo-java-driver/3.11/driver/getting-started/quick-start-pojo/ and all seems fine but one Person property is MongoDB dependent:
public final class Person {
private ObjectId id;
private String name;
private int age;
private Address address;}
This is org.bson.types.ObjectId id. This makes my domain layer dependent on MongoDB, and this actually what I would not call a POJO at all. Instead of ObjectId I would like to have String or other Java core class like Long or something like that. It could could be a kind of getter/setter too. How can I achieve this?
I tried to remove id from Person
package com.mongo_demo.domain;
public final class Person {
private String name;
private int age;
private Address address;}
and use this as my domain object, while to operate with MongoDB in DAO I will use child class:
package com.mongo_demo.mongo_domain;
public final class Person extends com.mongo_demo.domain.Person {
private ObjectId id;
}
Obviously my domain class now not have dependencies on MongoDB, but still lacks String id and no way to have getter method for it, as ObjectId id attribute is in child class.
I not sure is it fine to not have access to id value in my services code, because I could need to call delete by id operation, otherwise I will have to create my own object unique identifier, in addition to ObjectId id attribute, which will be natural key with consequent drawbacks.
PS No getter-setter methods shown, as I use Lombok #Data annotations instead.

Unable to use #Serialize with requestfactory

I've created an entity with a pojo (ProductVariations) using the label #Serialize to be persisted in GAE through objectify:
#Entity
public class Product extends DatastoreObject{
//Reference without the colors and size information
#Index private String ref;
private double price;
private String details;
private String description;
#Serialize private ProductVariations pVariations;
private List<String> tags = new ArrayList<String>();
//Getters & Setters
}
The problem is that I don't see how to access my pojo with requestfactory because ProductVariations is not a domain type.
In any other case I would use an embeded object but in this particular case I have a nested collection inside ProductVariations witch is a collection in itself (ProductVariations extends ArrayList).
Any suggestions in how to achieve this?
Thank you.
Not sure I understand your question, but you need to implement Serializable in Product if you want to send it over RPC.
Beyond that, are you having problems storing ProductVariations? It's an interesting concept. If it isn't working:
Can you keep ProductVariations in its own #Entity?
Then keep a Key in Product class (or a Long that can you can create a Key from).
For convenience you can also leave ProductVariations in Product but mark it with #Transient and then populate it from the Key/Long in the factory that does your ofy.get().

OO Design of JavaBeans

I'm questioning the way that I have been designing my JavaBeans. For example, say I have the following:
Employee - basic employee information:
private String employee_id;
private String first_name;
private String last_name;
private String phone;
private String deptNo;
etc..
WorkflowPlayer - details about an employee in a system workflow:
private String workflow_instance_id;
private String employee_id;
private String role_class_id;
private String role_required;
private Employee employee;
private RoleClass roleClass;
RoleClass - details of a type of role (Approver, SecurityReviewer, Originator, Instructor, Manager, etc..)
private String role_class_id;
private String name;
private String label;
private String description;
These three models also correspond directly to Database tables (Employee is a read only view for me, if that matters)
Then in my view I would do something like
workflow_player.employee.first_name
workflow_player.roleClass.label
Is it acceptable to make Employee an instance variable? Or should I instead be extending WorkflowPlayer with Employee and then do
workflow_player.first_name
this makes sense for employee but not for roleClass.
workflow_player.description //NO!
I just want to use a consistent [correct] pattern
Yes, it's ok to make Employee an instance variable if you are referring to it from another table. Subclassing in this case is wrong because from your description it sounds like workflow is not a specialized kind of employee. Ask yourself if the lifecycles of these entities are the same or different, and if the subclass is substitutable for the superclass in all situations.
Subclassing should be a last resort reserved for cases where some entity is a specialized version of another entity and you want to refer to the specialized versions by their superclass.
There are specific patterns where subclassing is used in Object-relational mapping: table per class hierarchy, table per subclass, table per concrete entity, etc. The Hibernate documentation describes them. You would use inheritance in mapping objects to tables when your tables fall into one of those patterns. Even if you're not using Hibernate that's still a good example to follow.
I think role classes are a great design approach, and many developers do not use them. This matches the canonical use of role classes: when an entity participates in different activities, and within those activities, the view of that type is different. A good example would be the following. Suppose we were modeling payroll. We have a user who is both one of the employees who is getting paid, and an administrator in the app. In Java, we would have to model that as role classes because we don't have multiple inheritance, but it's really a more accurate representation because the role class, if it does confer any additional behavior or properties, it is doing so in the context of its own behavior. So for instance, whatever powers you need to grant the administrator in the payroll is confined to that realm.
It's also not an either/or situation: in the Payroll, you might want to show that some employees are also managers. That probably would best be done with inheritance, but the role class is still valid, again, as a way of representing participation.
You can't map JavaBean directly to Tables, because OO is not the same as Relational (Database).
You could use an ORM, like Hibernate, to map you JavaBean to SGBD Tables properly.
From an OO point of view, beans should be like that
public class Employee {
private String id;
private String firstName;
private String lastName;
private String phone;
private String deptNo;
}
public class WorkflowPlayer {
private String id;
private String roleRequired;
private Employee employee;
private Role roleClass;
}
public class RoleClass {
private String id;
private String name;
private String label;
private String description;
}

Storing Objects in columns using Hibernate JPA

Is it possible to store something like the following using only one table? Right now, what hibernate will do is create two tables, one for Families and one for people. I would like for the familymembers object to be serialized into the column in the database.
#Entity(name = "family")
class Family{
private final List<Person> familyMembers;
}
class Person{
String firstName, lastName;
int age;
}
This is an horrible design and I'm really not recommending it (you should just create another table) but it is possible.
First, you'll need to use a byte[] attribute to hold a serialized version of the list of persons that will be stored in a BLOB in the database. So annotate it's getter with #Lob (I would make the getter and setter private to not expose them). Then, expose "fake" getter and setter to return or set a List<Person> from the byte[]. I'm using SerializationUtils from Commons Lang in the sample below (provide you own helper class if you don't want to import this library) to serialize/deserialize on the fly to/from the byte[]. Don't forget to mark the "fake" getter with #Transcient or Hibernate will try to create a field (and fail because it won't be able to determine the type for a List).
#Entity(name = "family")
class Family implements Serializable {
// ...
private byte[] familyMembersAsByteArray;
public Family() {}
#Lob
#Column(name = "members", length = Integer.MAX_VALUE - 1)
private byte[] getFamilyMembersAsByteArray() { // not exposed
return familyMembersAsByteArray;
}
private void setFamilyMembersAsByteArray((byte[] familyMembersAsByteArray() { // not exposed
this.familyMembersAsByteArray = familyMembersAsByteArray;
}
#Transient
public List<Person> getFamilyMembers() {
return (List<Person>) SerializationUtils.deserialize(familyMembersAsByteArray);
}
public void setParticipants(List familyMembers) {
this.familyMembersAsByteArray = SerializationUtils.serialize((Serializable) familyMembers);
}
}
Don't forget to make the Person class Serializable and to add a real serialVersionUID (I'm just showing a default here):
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
// ...
private String firstName, lastName;
private int age;
}
But, let me insist, this is an horrible design and it will be very fragile (changing Person might require to "migrate" the content of the BLOB to avoid deserialization issues and this will become painful. You should really reconsider this idea and use another table for the Person instead (or I don't get why you use a database).
#Type(type = "serializable")
private List<Person> familyMembers;
if you can't use hibernate annotations try this:
#Lob
private Serializable familyMembers;
public List<Person> getFamilyMembers(){
return (List) familyMembers;
}
public void setFamilyMembers(List<Person> family){
familyMembers = family;
}
Annotate the property with #Column and define the type to be ArrayList, not just List. And make Person implement Serializable.
But you should do this only if your motives are very clear, because this is the correct solution in some very rare cases. As Pascal noted, if you ever have to change Person you'll have headaches.
You can create pseudoproperty (getter and setter) which accepts/returns the serialized form, and annotate the familyMembers with #Transient. This would also need to annotate the getters, not fields, for all other properties.

Categories