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
Related
i'm using java, for example, i have 2 tables staff(id, name, status_id, company_id) and company(id, name), the corresponding entity looks like:
public class Staff {
private Integer id;
private String name;
private Integer statusId;
private Integer companyId;
private Company company;
}
public class Company {
private Integer id;
private String name;
private List<Staff> staffList;
}
for status_id of table staff, 0 means New, 1 represents Active and 2 stands for Inactive.
I need to show New, Active or Inactive on html page/excel when describe a staff status rather than 0, 1 or 2.
And I have a StaffDto:
public class StaffDto {
private Integer id;
private String name;
private Integer statusId;
private String companyName;
}
my questions are:
the statusName(New/Active/Inactive) should be in StaffDto, such that there is no need to calculate status name according to statusId on each client, right?
what is a good practice to get statusName base on statusId?
I should write code like
public class StaffDto {
private Integer statusId;
private String statusName;
public String getStatusName() {
switch(statusId) {
case 0: return "New";
case 1: return "Active";
case 2: return "Inactive";
}
}
}
is this a good practice? or something else(e.g. enum) is better?
if the logic of getting status name is added in StaffDto, what if there is another dtoj(e.g. ADto) also need to show status name, then I have to re-write this logic in ADto?
what if one client need to show New, Active or Inactive, while another client need to show A, B or C or something else, then what should I return in StaffDto? do I still return New, Active or Inactive in StaffDto, and other client need to calculate N, A or I base on statusId on their client? or should I return something else to client instead of xxxDto?
I too would go for enum as you mentioned, bind the status code to the name
then, you do not have to rewrite the logic in DTOs, Make your model have the enum rather than code or name
enum can have its own methods like getShortName for different representations
enum Status {
NEW(0), Active(1), InActive(2);
private final int code;
Status(int code) {
this.code = code;
}
public String getShortName() {
return this.name().substring(0, 1).toUpperCase();
}
public int getCode() {
return code;
}
}
I am new to REST API, so I am not sure whether I have phrased the question correctly.
I have a Java class with two attributes.
class TestClass {
private double rate;
private double quantity;
#ApiModelProperty
getRate() {
return rate;
}
#ApiModelProperty
getQuantity() {
return quantity;
}
}
I have an API, which when i call, fetches data from an SQL table and returns a JSON object as shown(I have used examples):
{
rate = 5;
quantity = 10;
}
I want to modify the output so that only either rate or quantity would be displayed depending on the condition. How do i do it?
You can have two API methods that each returns different object
class TestClassRate {
private double rate;
#ApiModelProperty
getRate() {
return rate;
}
}
class TestClassQuantity {
private double quantity;
#ApiModelProperty
getQuantity() {
return quantity;
}
}
what is the condition? if you want to show only not null field, you have to make the correct configuration of your json provider.
For example, if you're using Jackson :
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
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;
}
}
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'm still struggling with changing my Spring Application to use Hibernate with JPA to do database activities. Well apparently from a previous post I need an persistence.xml file. However do I need to make changes to my current DAO class?
public class JdbcProductDao extends Dao implements ProductDao {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
public List<Product> getProductList() {
logger.info("Getting products!");
List<Product> products = getSimpleJdbcTemplate().query(
"select id, description, price from products",
new ProductMapper());
return products;
}
public void saveProduct(Product prod) {
logger.info("Saving product: " + prod.getDescription());
int count = getSimpleJdbcTemplate().update(
"update products set description = :description, price = :price where id = :id",
new MapSqlParameterSource().addValue("description", prod.getDescription())
.addValue("price", prod.getPrice())
.addValue("id", prod.getId()));
logger.info("Rows affected: " + count);
}
private static class ProductMapper implements ParameterizedRowMapper<Product> {
public Product mapRow(ResultSet rs, int rowNum) throws SQLException {
Product prod = new Product();
prod.setId(rs.getInt("id"));
prod.setDescription(rs.getString("description"));
prod.setPrice(new Double(rs.getDouble("price")));
return prod;
}
}
}
Also my Product.Java is below
public class Product implements Serializable {
private int id;
private String description;
private Double price;
public void setId(int i) {
id = i;
}
public int getId() {
return id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("Description: " + description + ";");
buffer.append("Price: " + price);
return buffer.toString();
}
}
I guess my question would be,
How would my current classes change after using Hibernate + JPA with an Entity Manager
Did you check the section 12.6. JPA of the Chapter 12. Object Relational Mapping (ORM) data access in the official documentation? Everything you need to know is discussed there.
If this is an option, you should extend the JpaDaoSupport base class, it provides convenient methods like get/setEntityManagerFactory and getJpaTemplate() to be used by sublasses. If not, then get a EntityManagerFactory injected and use it to create a JpaTemplate. See the section 12.6.2. JpaTemplate and JpaDaoSupport for more details on this.
Also have a look at Getting Started With JPA in Spring 2.0 for a more complete sample (the blog post is a bit old but is not really outdated) that will show you how to rewrite the methods of your DAO.
Moreover, I suggest you to read this article: Generic DAO with Hibernate and Spring AOP, before deciding your design.