Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 75409a9

Browse files
committedApr 13, 2024
docs: embedded value + refactor
1 parent ffffab4 commit 75409a9

File tree

3 files changed

+80
-60
lines changed

3 files changed

+80
-60
lines changed
 

‎embedded-value/README.md

Lines changed: 71 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,57 @@
11
---
22
title: Embedded Value
3-
category: Structural
3+
category: Behavioral
44
language: en
5-
tag:
6-
- Data Access
7-
- Enterprise Application Pattern
5+
tag:
6+
- Data access
7+
- Enterprise patterns
8+
- Optimization
9+
- Performance
810
---
911

1012
## Also known as
11-
Aggregate Mapping, Composer
13+
14+
* Aggregate Mapping
15+
* Composer
16+
* Inline Value
17+
* Integrated Value
1218

1319
## Intent
14-
Many small objects make sense in an OO system that don’t make sense as
15-
tables in a database. An Embedded Value maps the values of an object to fields in the record of the object’s owner.
20+
21+
The Embedded Value design pattern aims to enhance performance and reduce memory overhead by storing frequently accessed immutable data directly within the object that uses it, rather than separately.
1622

1723
## Explanation
1824

1925
Real-world example
2026

21-
> Examples include currency-aware money objects and date
22-
ranges. Although the default thinking is to save an object as a table, no sane person would want a table of money values.
23-
> Another example would be the online orders which have a shipping address like street, city, state. We map these values of Shipping address object to fields in record of Order object.
27+
> In a library, the reference desk embeds commonly used resources like dictionaries and encyclopedias directly at the desk for quick and easy access, similar to how the Embedded Value design pattern integrates frequently used data directly within an object for efficiency.
2428
2529
In plain words
2630

2731
> Embedded value pattern let's you map an object into several fields of another object’s table.
2832
2933
**Programmatic Example**
3034

31-
Consider online order's example where we have details of item ordered and shipping address. We have Shipping address embedded in Order object. But in database we map shipping address values in Order record instead of creating a separate table for Shipping address and using foreign key to reference the order object.
35+
Consider an online ordering example where we have details of item ordered and shipping address. We have Shipping address embedded in Order object. But in database we map shipping address values in Order record instead of creating a separate table for Shipping address and using foreign key to reference the order object.
3236

3337
First, we have POJOs `Order` and `ShippingAddress`
3438

3539
```java
3640
public class Order {
3741

38-
private int id;
39-
private String item;
40-
private String orderedBy;
41-
private ShippingAddress ShippingAddress;
42+
private int id;
43+
private String item;
44+
private String orderedBy;
45+
private ShippingAddress ShippingAddress;
4246

43-
public Order(String item, String orderedBy, ShippingAddress ShippingAddress) {
44-
this.item = item;
45-
this.orderedBy = orderedBy;
46-
this.ShippingAddress = ShippingAddress;
47-
}
47+
public Order(String item, String orderedBy, ShippingAddress ShippingAddress) {
48+
this.item = item;
49+
this.orderedBy = orderedBy;
50+
this.ShippingAddress = ShippingAddress;
51+
}
52+
}
4853
```
54+
4955
```java
5056
public class ShippingAddress {
5157

@@ -60,48 +66,56 @@ public class ShippingAddress {
6066
}
6167
}
6268
```
69+
6370
Now, we have to create only one table for Order along with fields for shipping address attributes.
6471

6572
```Sql
66-
CREATE TABLE Orders (Id INT AUTO_INCREMENT, item VARCHAR(50) NOT NULL, orderedBy VARCHAR(50) city VARCHAR(50), state VARCHAR(50), pincode CHAR(6) NOT NULL, PRIMARY KEY(Id))
73+
CREATE TABLE Orders
74+
(
75+
Id INT AUTO_INCREMENT,
76+
item VARCHAR(50) NOT NULL,
77+
orderedBy VARCHAR(50) city VARCHAR (50),
78+
state VARCHAR(50),
79+
pincode CHAR(6) NOT NULL,
80+
PRIMARY KEY (Id)
81+
)
6782
```
6883

6984
While performing the database queries and inserts, we box and unbox shipping address details.
7085

7186
```java
72-
final String INSERT_ORDER = "INSERT INTO Orders (item, orderedBy, city, state, pincode) VALUES (?, ?, ?, ?, ?)";
87+
final String INSERT_ORDER="INSERT INTO Orders (item, orderedBy, city, state, pincode) VALUES (?, ?, ?, ?, ?)";
7388

74-
public boolean insertOrder(Order order) throws Exception {
75-
var insertOrder = new PreparedStatement(INSERT_ORDER);
76-
var address = order.getShippingAddress();
89+
public boolean insertOrder(Order order)throws Exception{
90+
var insertOrder=new PreparedStatement(INSERT_ORDER);
91+
var address=order.getShippingAddress();
7792
conn.setAutoCommit(false);
78-
insertIntoOrders.setString(1, order.getItem());
79-
insertIntoOrders.setString(2, order.getOrderedBy());
80-
insertIntoOrders.setString(3, address.getCity());
81-
insertIntoOrders.setString(4, address.getState());
82-
insertIntoOrders.setString(5, address.getPincode());
83-
84-
var affectedRows = insertIntoOrders.executeUpdate();
85-
if(affectedRows == 1){
93+
insertIntoOrders.setString(1,order.getItem());
94+
insertIntoOrders.setString(2,order.getOrderedBy());
95+
insertIntoOrders.setString(3,address.getCity());
96+
insertIntoOrders.setString(4,address.getState());
97+
insertIntoOrders.setString(5,address.getPincode());
98+
99+
var affectedRows=insertIntoOrders.executeUpdate();
100+
if(affectedRows==1) {
86101
Logger.info("Inserted successfully");
87-
}else{
88-
Logger.info("Couldn't insert " + order);
102+
} else {
103+
Logger.info("Couldn't insert "+order);
89104
}
90105
}
91106
```
92107

93108
## Class diagram
94-
![alt text](./etc/embedded-value.urm.png "Embedded value class diagram")
109+
110+
![Embedded Value](./etc/embedded-value.urm.png "Embedded Value class diagram")
95111

96112
## Applicability
97113

98-
Use the Embedded value pattern when
114+
Use the Embedded value pattern when:
99115

100-
* Many small objects make sense in an OO system that don’t make sense as tables in a database.
101-
* The simplest cases for Embedded Value are the clear, simple Value Objects like money and date range.
102-
* If you’re mapping to an existing schema, you can use this pattern when a table contains data that you want to split into more than one object in memory. This can occur when you want to factor out some behaviour in object model.
103-
* In most cases you’ll only use Embedded Value on a reference object when the association between them is single valued at both ends (a one-to-one association).
104-
* It can only be used for fairly simple dependents. A solitary dependent, or a few separated dependents, works well.
116+
* An application requires high performance and the data involved is immutable.
117+
* Memory footprint reduction is critical, especially in environments with limited resources.
118+
* Objects frequently access a particular piece of immutable data.
105119

106120
## Tutorials
107121

@@ -111,14 +125,22 @@ Use the Embedded value pattern when
111125

112126
## Consequences
113127

114-
* The great advantage of Embedded Value is that it allows SQL queries to be made against the values in the dependent object.
115-
* The embedded value object has no persistence behaviour at all.
116-
* While using this, you have to be careful that any change to the dependent marks the owner as dirty—which isn’t an issue with Value Objects that are replaced in the owner.
117-
* Another issue is the loading and saving. If you only load the embedded object memory when you load the owner, that’s an argument for saving both in the same table.
118-
* Another question is whether you’ll want to access the embedded objects' data separately through SQL. This can be important if you’re reporting through SQL and don’t have a separate database for reporting.
128+
Benefits:
129+
130+
* Reduces the memory overhead by avoiding separate allocations for immutable data.
131+
* Improves performance by minimizing memory accesses and reducing cache misses.
132+
133+
Trade-offs:
119134

135+
* Increases complexity in object design and can lead to tightly coupled systems.
136+
* Modifying the embedded value necessitates changes across all objects that embed this value, which can complicate maintenance.
137+
138+
## Related Patterns
139+
140+
[Flyweight](https://java-design-patterns.com/patterns/flyweight/): Shares objects to support large quantities using a minimal amount of memory, somewhat similar in intent but different in implementation.
141+
[Singleton](https://java-design-patterns.com/patterns/singleton/): Ensures a class has only one instance and provides a global point of access to it, can be used to manage a shared embedded value.
120142

121143
## Credits
122144

123-
* [Fowler, Martin - Patterns of enterprise application architecture-Addison-Wesley](https://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)
124-
* [Ram N Java](https://ramj2ee.blogspot.com/2013/08/embedded-value-design-pattern.html)
145+
* [Patterns of Enterprise Application Architecture](https://amzn.to/4452Idd)
146+
* [Ram N Java](https://ramj2ee.blogspot.com/2013/08/embedded-value-design-pattern.html)

‎embedded-value/src/main/java/com/iluwatar/embedded/value/DataSource.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ public Stream<Order> queryOrders() {
141141
rSet.getString(6)));
142142
ordersList.add(order);
143143
}
144-
rSet.close();
145144
} catch (SQLException e) {
146145
LOGGER.error(e.getMessage(), e.getCause());
147146
}
@@ -166,7 +165,6 @@ public Order queryOrder(int id) throws SQLException {
166165
rSet.getString(5), rSet.getString(6));
167166
order = new Order(rSet.getInt(1), rSet.getString(2), rSet.getString(3), address);
168167
}
169-
rSet.close();
170168
} catch (Exception e) {
171169
LOGGER.error(e.getLocalizedMessage(), e.getCause());
172170
}
@@ -192,7 +190,7 @@ public void removeOrder(int id) throws Exception {
192190
}
193191

194192
@Override
195-
public boolean deleteSchema() throws Exception {
193+
public boolean deleteSchema() {
196194
try {
197195
deleteschema.execute(DELETE_SCHEMA);
198196
queryOrders.close();

‎embedded-value/src/main/java/com/iluwatar/embedded/value/DataSourceInterface.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,22 @@
3636
*/
3737
interface DataSourceInterface {
3838

39-
final String JDBC_URL = "jdbc:h2:mem:Embedded-Value";
39+
String JDBC_URL = "jdbc:h2:mem:Embedded-Value";
4040

41-
final String CREATE_SCHEMA = "CREATE TABLE Orders (Id INT AUTO_INCREMENT, item VARCHAR(50) NOT NULL, orderedBy VARCHAR(50)"
41+
String CREATE_SCHEMA = "CREATE TABLE Orders (Id INT AUTO_INCREMENT, item VARCHAR(50) NOT NULL, orderedBy VARCHAR(50)"
4242
+ ", city VARCHAR(50), state VARCHAR(50), pincode CHAR(6) NOT NULL, PRIMARY KEY(Id))";
4343

44-
final String GET_SCHEMA = "SHOW COLUMNS FROM Orders";
44+
String GET_SCHEMA = "SHOW COLUMNS FROM Orders";
4545

46-
final String INSERT_ORDER = "INSERT INTO Orders (item, orderedBy, city, state, pincode) VALUES(?, ?, ?, ?, ?)";
46+
String INSERT_ORDER = "INSERT INTO Orders (item, orderedBy, city, state, pincode) VALUES(?, ?, ?, ?, ?)";
4747

48-
final String QUERY_ORDERS = "SELECT * FROM Orders";
48+
String QUERY_ORDERS = "SELECT * FROM Orders";
4949

50-
final String QUERY_ORDER = QUERY_ORDERS + " WHERE Id = ?";
50+
String QUERY_ORDER = QUERY_ORDERS + " WHERE Id = ?";
5151

52-
final String REMOVE_ORDER = "DELETE FROM Orders WHERE Id = ?";
52+
String REMOVE_ORDER = "DELETE FROM Orders WHERE Id = ?";
5353

54-
final String DELETE_SCHEMA = "DROP TABLE Orders";
54+
String DELETE_SCHEMA = "DROP TABLE Orders";
5555

5656
boolean createSchema() throws SQLException;
5757

0 commit comments

Comments
 (0)
Please sign in to comment.