How to implement One-to-one unidirectional association in Java (without ORM). I think bidirectional is possible. Association means both classes (say Part and PartNumber) need to exist independently, one to one means only one part number for one part and vice versa, unidirectional means part should know about part number but opposite. Now how Part number will know whether it has been assigned already. If we sacrifice independent existence of PartNumber then its composition.
You could implement this as either a unidirectional or a bidirectional association. Either will work. Ensuring that the 1-to-1 property is invariant maintained can be done in various ways:
In the bidirectional case, have the setters use the forward or reverse link to ensure that the object at the other end is not already related, and maybe break that relationship.
In the unidirectional case, by removing the ability to set a Part's PartNumber or a PartNumber's Part; e.g. have the Part create its own PartNumber in its constructor.
Another alternative is to make PartNumber a "value-based class", and always use PartNumber.equals(Object) to test for equality.
I found an implementation here: http://programmersthing.blogspot.in/2017/06/java-concepts.html
1.Customer Class :
import java.util.ArrayList;
public class Customer {
private String name;
ArrayList<Order> orders = new ArrayList<Order>();
public Customer(String name) {
this.name = name;
}
public String getName() {
return name;
}
public ArrayList<Order> getOrders() {
return orders;
}
public void addOrder(Order order) {
orders.add(order);
}
}
2.LineItem Class :
public class LineItem {
private int quantity;
Product products;
public LineItem(int quantity, Product products) {
this.quantity = quantity;
this.products = products;
}
public double calculateLineItemCost() {
return (quantity * products.calculatePriceAfterDiscount());
}
public int getQuantity() {
return quantity;
}
public Product getProducts() {
return products;
}
}
Related
I am trying to design an API which involves book a transaction to the system. The system will then generate a transaction ID that uniquely identifies the transaction.
I would like to define the Transaction class as a immutable one, like this:
public class Transaction {
private final double quantity;
private final BigDecimal price;
public Order(double quantity, BigDecimal price) {
this.quantity = quantity;
this.price = price;
}
public double getQuantity() {
return quantity;
}
public BigDecimal getPrice() {
return price;
}
}
The client call the API to create a new transaction:
public void storeTransaction(Transaction t)
But if I do this, how can I store the generated transaction ID?
1. Option 1
I can add an mutable state to the transaction class:
public class Transaction {
private final double quantity;
private final BigDecimal price;
private String transactionID;
public Order(double quantity, BigDecimal price) {
this.quantity = quantity;
this.price = price;
}
public double getQuantity() {
return quantity;
}
public BigDecimal getPrice() {
return price;
}
public String getTransactionID() {
return transactionID;
}
public void setTransactionID(String id) {
transactionID = id;
}
}
But this will make the Transaction class mutable.
Option 2
I can keep using the immutable Transaction and expose the API like this:
public String storeTransaction(Transaction t)
So instead of save the transaction id in the Transaction class, I could return it to our API user. But this does not look perfect for me as well because the user has to maintain an ID->Transaction relationship.
What is the best practice for designing this type of scenario?
You can generate the id in your constructor:
public class Transaction {
private final double quantity;
private final BigDecimal price;
private String transactionID;
public Order(double quantity, BigDecimal price) {
this.transactionID = this.generateID();
this.quantity = quantity;
this.price = price;
}
}
Now just implement a generateID() method to fill in the details.
Your storeTransaction() method could return the saved transaction which also contained the id.
public Transaction storeTransaction(Transaction t) {
...
}
And your Transaction class could have two constructors, one with the transaction id (for when it is known) and one without.
Your storeTransaction() method could save transaction with no id is present or if an id was present:
throw an exception if you want to keep your transactions immutable in your database or
update the existing transaction if you don't need immutability in the database.
The storeTransaction() method would return a new Transaction object containing all the details of the saved transaction (if it didn't throw an exception, of course).
Well, finalizing it does not make it that immutable. It is quite easy to change a final field in java, even easier than accessing a private field. Therefore I would create a mutable field, but it's setter does only work if the field is currently null. So you can only set it once (when it's generated). If the field is not null then you can throw an IllegalStateException
I try to map my DTO objects to my JPA entities. I have a Collection of children in my ParentEntity. They can be added addChild(). Using the Adder is supported by Mapstruct via the CollectionMappingStrategy (http://mapstruct.org/documentation/dev/reference/html/#collection-mapping-strategies).
This works fine if I create new entities, but fails to clear the children on updating before adding the new children.
The Mapstruct manual says (http://mapstruct.org/documentation/dev/reference/html/#updating-bean-instances):
Collection- or map-typed properties of the target bean to be updated will be cleared and then populated with the values from the corresponding source collection or map.
What am I missing? Is there an additional option I have to set? There is a full example with test case to reproduce the problem at https://github.com/davidfuhr/mapstruct-jpa-child-parent
Here are the classes:
public class ParentEntity {
private String name;
private List<ChildEntity> children = new ArrayList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ChildEntity> getChildren() {
return children;
}
public void addChild(ChildEntity child) {
children.add(child);
child.setMyParent(this);
}
public void removeChild(ChildEntity child) {
children.remove(child);
child.setMyParent(null);
}
}
public class ChildEntity {
private String name;
private ParentEntity myParent;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ParentEntity getMyParent() {
return myParent;
}
public void setMyParent(ParentEntity myParent) {
this.myParent = myParent;
}
}
public class ParentDto {
private String name;
private List<ChildDto> children;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ChildDto> getChildren() {
return children;
}
public void setChildren(List<ChildDto> children) {
this.children = children;
}
}
public class ChildDto {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface SourceTargetMapper {
SourceTargetMapper MAPPER = Mappers.getMapper(SourceTargetMapper.class);
ParentEntity toEntity(ParentDto s);
ParentEntity updateEntity(ParentDto s, #MappingTarget ParentEntity e);
#Mapping(target = "myParent", ignore = true)
ChildEntity toEntity(ChildDto s);
}
The text in the documentation need to be rephrased. The problem is that especially for collections, there's no good way to handle this out of the box in MapStruct. I'm currently writing some new text for the documentation.
Consider this (when thinking what MapStruct should do for updating collections in general):
What if there's no match: should the non-matching elements be removed?
Should the non matching source elements be added?
What exactly constitutes to a match: equals? hashcode? comparator==0?
Can there be more than one match (Lists, but also depending on what is considered a match.)
How should the resulting collection be sorted?
Should a newly created object be added to a persistence context?
What about JPA child-parent relations?
About the latter one, Dali (Eclipse) also generates remove methods. So should MapStruct call these in the light of the above?
At this moment it works like this: whenever the user wants a collection update method, MapStruct generates a regular call to element mappings (in stead of an update call), because it is the only sensible thing to do. All the remainder is highly dependent on the use-case. If you need to clear the collection at before hand, use the #BeforeMapping to clear it.
Note: I just fixed an issue that handles also adders in this fashion in stead of the vague error message you get now.
If you want a nice way to handle child/parent relations and integrate them with JPA.. have a look at the examples.
I have two immutable classes: User and Department, they are connected using a bidirectional association - User has a reference to Department and Department has a list of Users. How to create a new Department instance with the provided Users?
Code:
class User {
private final Department department;
private final String name;
public User(Department department, String name) {
this.department = department;
this.name = name;
}
}
class Department {
private final List<User> users;
private final String name;
public Department(List<User> users, String name) {
this.users = new ArrayList<>(users);
this.name = name;
}
}
I feel in you case you can slightly modify your design and use special UsersBuilder, i.e.
class Department {
final List<User> users;
final String name;
public Department(String name) {
this.users = UsersBuilder.buildUsers(this);
this.name = name;
}
}
class UsersBuilder {
public static List<User> buildUsers(Department department) {
List<User> usersList = new ArrayList<>();
// add users to the list via department reference
return Collections.unmodifiableList(usersList);
}
}
In general, it is not really good idea to use object's reference before its constructor finishes; but in this particular case it looks safe.
In this case these objects will be really immutable.
You can produce immutable Departments and Users with an extra constructor on Department. From the questions' code, it is inferred that
A User object is just an association between a String and a Department
User references can't exist without a Department reference.
Since Users are truly just Strings associated to a Department, a Department can be constructed with a List<String> that represents all User names to be included and use that List<String> to create a List<User> within the Department constructor.
Note: what #andremoniy said about letting this escape from a constructor should not be made a habit of, but it is safe in this case since it is only being passed to a User instance's constructor where that User instance can't be accessed before the Department constructor returns.
Here's what it would look like, in Java 8:
public final class User {
private final Department department;
private final String name;
public User(Department department, String name) {
this.department = department;
this.name = name;
}
public Department getDepartment() {
return department;
}
public String getName() {
return name;
}
}
public final class Department {
private final List<User> users;
private final String name;
///Reversed argument list to avoid collision after erasure
public Department(String name, List<String> users) {
this.users = Collections.unmodifiableList(users.stream()
.map((s) -> new User(this,s)).collect(Collectors.toList()));
this.name = name;
}
public Department(List<User> users, String name) {
this.users = Collections.unmodifiableList(users);
this.name = name;
}
public List<User> getUsers() {
return users;
}
public String getName() {
return name;
}
}
One issue this solution has is that once a Department instance is created, it can be added to new instances of User without the constraint that a new instance of Department be created with an updated List. Consider other abstractions or creational patterns (a full blown Builder implementation where all constructors are private would be a good match here) if you need to support the addition/deletion of users from a Department while maintaining immutability.
Instantiate Department with empty list of users. Then use the Department to instantiate User and add the user instance to the Department's users list.
One approach is to slightly alter what you understand immutable to mean. In object oriented design it is conventional to distinguish between the attributes of an object and its associations. Associated objects are different entities to which the object has references. If you relax the definition of immutable to mean that the attributes of the object do not change, but allow the associations to change, you avoid this kind of problem.
In your case, User and Department objects would be associated with each other, and each would have a name attribute.
I think this is a matter of modeling as well. This is ok to think that an User has a Department and a Department have Users, but the question is how deep can you look into data from User and Department ends?
Does it make sense unless conceptually you to access user.department.user[2].name? What about department.user[10].addresses[1].street?
I really don't think so on most scenarios. It's a matter of information domain. You have bondaries while accessing data and this can also be expressed somehow into your models.
If Object Modeling kind represents the real world, this is ok to think that when you go to a department, you will see dozens of people working there and most likely all you will be able to know about them is the counting and the their names perhaps. So what slices of data you should be able to see from your object?
My approach for this is:
interface PersonInfo {
String name();
String lastName();
default fullName() { return name() + " " + lastName(); }
static PersonInfoBuilder personInfo() { return new PersonInfoBuilder(); }
static class PersonInfoBuilder {
...
}
}
interface Person extends PersonInfo {
DepartmentInfo department();
Set<Address> addresses();
//...
}
interface DepartmentInfo {
String name();
String building();
// builder ...
}
interface Department extends DepartmentInfo {
Set<PersonInfo> employees();
// ...
}
I don't think i'd need to show how the builders would work since if you noticed, for this scenario, the bidirectional nature of relationship is never there. So when you build a Person, all you need is the DepartmentInfo (department no employees not required), and the same is valid when you build a Department, when all you need to have is the PersonInfo from department's employees.
That's my way to think this problem conceptually. Any comments?
My solution is to: split one of the immutable classes into two classes: a class with the attributes and a class with the bidirectional association:
class Department {
private final String name;
public Department(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class User {
private final Department department;
private final String name;
public User(Department department, String name) {
this.department = department;
this.name = name;
}
}
class DepartmentWithUsers {
private final List<User> users;
private final Department department;
public DepartmentWithUsers(Department department, List<User> users) {
this.department = department;
this.users = new ArrayList<>(users);
}
}
So to create a new user and a department instance you have to:
create a new Department instance
create a new User instance and pass the created Department instance
create a new DepartmentWithUsers instance and pass the created User instance
I am having confusing over how to choose my data structure. Lets say i have following data
Product,Price,Company,Total available.. which i get from db. Now i want to represent this in lets say excel or csv in same order as i get from db company wise.
So i choose below data structure.
Map<String, TreeMap<Integer, TreeMap<String, String>>> .
First String represents Company
Integer represents position of record in db so that i can display in same order.
The TreeMap contains other values.
Can I choose any better data structure for this requirement.
Yes, absolutely.
A better solution would be object-oriented:
public class Product {
private String name;
private String company;
private Money total;
private boolean available;
// Add necessary methods.
}
The data structure would be a List<Product>.
Your way is too primitive.
Traditional data structures follow a structured programming paradigm. Object oriented programming has roots in structured programming, but adds in the concept of behavior locality. In short, the data is not just centralized, but the behavior (methods) that go with the data is centralized.
This allows data hiding (useful for maintenance, as the right data format tends to change over time), and opens the door to other more advance behaviors (polymorphisim is possible because the behavior is localized). However, it doesn't do much for a pure play data structure approach. The closest we have to old school data structures are objects which represent them.
When selecting a data structure, if you really don't have an idea of what is important, you really don't have the criteria which would allow you to select one data structure over another. Sure, you could just always use HashMap and HashSet and that would be fine a lot of the time; but, there are trivial examples where those selections are probably the worst choices. In short, you need to know the access patterns to make the right choice.
As duffymo suggests, you should consider an oop approach. Consider using something like the following example:
import java.util.ArrayList;
public class Product {
private String name;
private double price;
private String company;
private int total;
private boolean available;
public Product(String name, double price, String company, int total,
boolean available) {
super();
this.name = name;
this.price = price;
this.company = company;
this.total = total;
this.available = available;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
#Override
public String toString() {
return "Product [name=" + name + ", price=" + price + ", company="
+ company + ", total=" + total + ", available=" + available
+ "]";
}
public static void main(String[] args) {
ArrayList<Product> products = new ArrayList<Product>();
Product product1 = new Product("PlayStation 4", 300, "Sony", 10, true);
Product product2 = new Product("XBOX One", 400, "Microsoft", 0, false);
Product product3 = new Product("WiiU", 250, "Nintendo", 5, true);
products.add(product1);
products.add(product2);
products.add(product3);
System.out.println("-- Products --");
for (Product product : products) {
System.out.println(product.toString());
}
}
}
It will produce the following output:
-- Products --
Product [name=PlayStation 4, price=300.0, company=Sony, total=10, available=true]
Product [name=XBOX One, price=400.0, company=Microsoft, total=0, available=false]
Product [name=WiiU, price=250.0, company=Nintendo, total=5, available=true]
As you can see, you will be able to easily manage your list of items.
Hope it helps.
Clemencio Morales Lucas.
I have a Base Class.
#Data
class BaseDocument{
String id;
String name;
//Other fields
}
Say I have many classes that extends BaseDocument one below.
class NoteDocument extends BaseDocument{
String description;
Long lastModifiedDate;
//etc
}
It does not make sense to me to send entire document to UI in some cases. Most of the cases I need only id and name.
So for every document I have a VO class.
#Data
class BaseVO {
private String id;
private String name;
}
#Data
class NoteVO extends BaseVO{
//Nothing here now
}
And in NoteDocument I have.
public NoteVO getVo(){
Assert.notNull(getId());
NoteVO noteVo = new NoteVO();
noteVo.setName(getName());
noteVo.setId(getId());
return noteVo;
}
Now I have to copy this method in all the classes that extends BaseDocument.
Instead, I changed my BaseDocument like below.
#Data
class BaseDocument<V extends BaseVO>{
String id;
String name;
public V getVo(Class className) {
Assert.notNull(getId());
V vo = null;
try {
vo = (V) className.newInstance();
vo.setName(getName());
vo.setId(getId());
} catch (IllegalAccessException|InstantiationException e){
e.printStackTrace();
}
Assert.notNull(vo);
return vo;
}
}
I am new to generics. My first question, is this a good practice. Are there any problems in using reflection to create instance, any performance issues? Is there any better way to do achieve (write less code) this.
Edit: Suppose I need to display note in UI, Along with note I need to display name of the User who created note. I am using mongodb, when I save the note I also save UserVO in note, which will have user id and name of the user. If I save only user id while saving the note, I will have to do one more query to get the name of user while displaying. I want to avoid this.
Do not use reflection; use inheritance and maybe covariant return types instead. It will be faster, clearer, more precise, and easier to maintain. You may also find it useful to add methods to populate your VOs incrementally. I didn't come up with a clean way to apply generics to this situation, but I don't think you need them:
class BaseVO {
String id;
String name;
void setId(String id) {
this.id = id;
}
void setName(String name) {
this.name = name;
}
}
class NoteVO extends BaseVO {
// ...
}
#Data
class BaseDocument {
String id;
String name;
//Other fields
protected void populateBaseVO(BaseVO vo) {
vo.setId(id);
vo.setName(name);
}
public BaseVO getVO() {
BaseVO vo = new BaseVO();
populateBaseVO(vo);
return vo;
}
}
#Data
class NoteDocument extends BaseDocument {
String description;
Long lastModifiedDate;
// ....
protected void populateNoteVO(NoteVO vo) {
populateBaseVO(vo);
// ...
}
public NoteVO getVO() {
NoteVO vo = new NoteVO();
populateNoteVO(vo);
return vo;
}
}