Skip to content

Commit ae53c27

Browse files
authored
Merge pull request iluwatar#1 from iismail1997/Issue#1312
Issue#1312
2 parents 80a2256 + 093eeca commit ae53c27

25 files changed

+1186
-0
lines changed

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@
218218
<module>factory</module>
219219
<module>separated-interface</module>
220220
<module>special-case</module>
221+
<module>row-data-gateway</module>
221222
<module>parameter-object</module>
222223
<module>active-object</module>
223224
<module>model-view-viewmodel</module>

row-data-gateway/ReadMe.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Row Data Gateway pattern
2+
3+
## Intent
4+
5+
The **Row Data Gateway Pattern** provides programmers with an object to perform CRUD
6+
(create, read, update and delete) operations for a single record (db row),
7+
hence referred to as a _gateway_.
8+
9+
![alt text](./etc/sql-crud-operation.png "SQL CRUD Operations")
10+
11+
This pattern is normally used for **Transaction Scripts** because it provides reusable
12+
database operations with regular programing language methods.
13+
14+
However, this has a few drawbacks, most objects are created to satisfy business
15+
requirements, adding database logic to these objects increases the code complexity.
16+
17+
## UML for this implementation of Row Data Gateway Pattern
18+
19+
![alt text](./etc/parrotUML.png "SQL CRUD Operations")
20+
21+
## Database (MySQL)
22+
23+
### Database setup
24+
**Note**
25+
<span style="color: green"> Follow this tutorial to set up the database https://dev.mysql.com/doc/mysql-getting-started/en/ </span>
26+
27+
After setting up the database create the following user, with username `admin` and password `admin123`.
28+
29+
`CREATE USER 'admin'@'localhost' IDENTIFIED BY 'admin123';`
30+
### Tables
31+
32+
**Note** these will be created at runtime of application,
33+
but db needs to be set up first.
34+
35+
<span style="color: orange"> These scripts can be found in /src/main/resources/db-scripts </span>
36+
37+
- ParrotType.sql > Contains a list of different types of parrots
38+
- OwnedParrot.sql > Owner's parrot(s) (name, age, color, tamed, reference to ParrotType,
39+
reference to ParrotOwner) and foreign key to Parrots table
40+
for parrot specific species.
41+
42+
### References
43+
44+
#### Row Data Gateway Pattern
45+
https://www.sqlshack.com/crud-operations-in-sql-server/#gallery-1
46+
https://www.sourcecodeexamples.net/2018/04/row-data-gateway.html
47+
https://www.martinfowler.com/eaaCatalog/rowDataGateway.html
48+
https://github.com/richard-jp-leguen/glorified-typings/blob/master/ta-material/soen343-f2010/tut-71.implementing-row-data-gateway.md/
49+
50+
#### MySql User references
51+
52+
https://docs.rackspace.com/support/how-to/create-and-edit-users-in-mysql/

row-data-gateway/etc/ParrotUML.png

69.5 KB
Loading
12.8 KB
Loading

row-data-gateway/pom.xml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>java-design-patterns</artifactId>
7+
<groupId>com.iluwatar</groupId>
8+
<version>1.25.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>row-data-gateway</artifactId>
13+
14+
<properties>
15+
<maven.compiler.source>12</maven.compiler.source>
16+
<maven.compiler.target>12</maven.compiler.target>
17+
</properties>
18+
<dependencies>
19+
<dependency>
20+
<groupId>mysql</groupId>
21+
<artifactId>mysql-connector-java</artifactId>
22+
<version>8.0.25</version>
23+
<scope>compile</scope>
24+
</dependency>
25+
<dependency>
26+
<groupId>org.apache.commons</groupId>
27+
<artifactId>commons-lang3</artifactId>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.junit.jupiter</groupId>
31+
<artifactId>junit-jupiter-engine</artifactId>
32+
<scope>test</scope>
33+
</dependency>
34+
<dependency>
35+
<groupId>junit</groupId>
36+
<artifactId>junit</artifactId>
37+
<scope>test</scope>
38+
</dependency>
39+
<dependency>
40+
<groupId>org.mockito</groupId>
41+
<artifactId>mockito-inline</artifactId>
42+
<scope>test</scope>
43+
</dependency>
44+
45+
</dependencies>
46+
47+
</project>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import ParrotDataModel.OwnedParrot;
2+
import ParrotRowGateWay.OwnedParrotFinder;
3+
import ParrotRowGateWay.OwnedParrotGateWay;
4+
import ParrotRowGateWay.ParrotRegistry;
5+
import ParrotRowGateWay.ParrotTypeRegistry;
6+
import db.DataBaseConnection;
7+
8+
import java.sql.Connection;
9+
import java.sql.SQLException;
10+
11+
public class App {
12+
public static void main(String[] args) throws SQLException {
13+
// Getting an existing parrot and printing information
14+
OwnedParrot myOldParrot = new OwnedParrot();
15+
16+
OwnedParrotFinder finder = new OwnedParrotFinder();
17+
OwnedParrotGateWay ownedParrotGateWay = finder.findById(1);
18+
19+
myOldParrot.setOwnedParrotId(ownedParrotGateWay.getOwnedParrotId());
20+
myOldParrot.setParrotTypeId(ownedParrotGateWay.getParrotTypeId());
21+
myOldParrot.setParrotName(ownedParrotGateWay.getParrotName());
22+
myOldParrot.setColor(ownedParrotGateWay.getColor());
23+
myOldParrot.setParrotAge(ownedParrotGateWay.getParrotAge());
24+
myOldParrot.setTamed(ownedParrotGateWay.getTamed());
25+
26+
myOldParrot.printParrotInformation();
27+
28+
// Insert a new record into the DB
29+
System.out.println("Types of parrots mapping id to species:");
30+
ParrotTypeRegistry.printParrotTypeInformation();
31+
OwnedParrot myNewParrot = new OwnedParrot();
32+
myNewParrot.setParrotTypeId(1);
33+
myNewParrot.setParrotName("Mikey");
34+
myNewParrot.setParrotAge(1);
35+
myNewParrot.setColor("Blue and Gold");
36+
myNewParrot.setTamed(true);
37+
38+
OwnedParrotGateWay myNewParrotGateWay = new OwnedParrotGateWay(myNewParrot);
39+
myNewParrotGateWay.insert();
40+
myNewParrot.setOwnedParrotId(myNewParrotGateWay.getOwnedParrotId());
41+
myNewParrot.printParrotInformation();
42+
43+
44+
}
45+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package ParrotDataModel;
2+
3+
import ParrotRowGateWay.ParrotTypeRegistry;
4+
import com.mysql.cj.util.StringUtils;
5+
import lombok.Getter;
6+
import lombok.Setter;
7+
import org.apache.commons.lang3.BooleanUtils;
8+
9+
import java.sql.SQLException;
10+
11+
12+
@Getter
13+
@Setter
14+
public class OwnedParrot {
15+
16+
private Integer ownedParrotId;
17+
18+
private Integer parrotTypeId;
19+
20+
private String parrotName;
21+
22+
private Integer parrotAge;
23+
24+
private String color;
25+
26+
private Boolean tamed;
27+
28+
public void printParrotInformation() throws SQLException {
29+
StringBuilder sb = new StringBuilder();
30+
sb.append("My parrot information: \n");
31+
if(ownedParrotId != null)
32+
sb.append("ParrotId: " + ownedParrotId + "\n");
33+
if(this.parrotTypeId != null)
34+
sb.append("Species: " + ParrotTypeRegistry.getParrotTypeById(parrotTypeId).getSpecies() + "\n");
35+
if(!StringUtils.isNullOrEmpty(parrotName))
36+
sb.append("Name: " + parrotName + "\n");
37+
if(parrotAge != null)
38+
sb.append("Age: " + parrotAge + "\n");
39+
if(StringUtils.isNullOrEmpty(color))
40+
sb.append("Name: " + color + "\n");
41+
if(tamed != null)
42+
sb.append("Tamed: " + BooleanUtils.toStringYesNo(tamed));
43+
44+
String parrotInformation = sb.toString();
45+
System.out.println(parrotInformation);
46+
}
47+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package ParrotDataModel;
2+
3+
import lombok.Getter;
4+
import lombok.Setter;
5+
6+
@Getter
7+
@Setter
8+
public class ParrotType {
9+
10+
public ParrotType(Integer parrotTypeId, String species) {
11+
this.parrotTypeId = parrotTypeId;
12+
this.species = species;
13+
}
14+
15+
private Integer parrotTypeId;
16+
17+
private String species;
18+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package ParrotRowGateWay;
2+
3+
import db.DataBaseConnection;
4+
5+
import java.sql.Connection;
6+
import java.sql.PreparedStatement;
7+
import java.sql.ResultSet;
8+
import java.sql.SQLException;
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
12+
public class OwnedParrotFinder {
13+
14+
private static final String FIND_ALL = "Select * from OwnedParrot";
15+
private static final String FIND_BY_ID = "Select * from OwnedParrot where OwnedParrotId=?";
16+
private static final String COUNT_FROM_OWNED_PARROT = "Select Count(*) as count from OwnedParrot";
17+
18+
public static final String OWNED_PARROT_ID = "OwnedParrotId";
19+
public static final String PARROT_TYPE_ID = "ParrotTypeId";
20+
public static final String PARROT_NAME = "ParrotName";
21+
public static final String PARROT_AGE = "ParrotAge";
22+
public static final String COLOR = "Color";
23+
public static final String TAMED = "Tamed";
24+
25+
private DataBaseConnection db;
26+
27+
public OwnedParrotFinder() {
28+
29+
}
30+
31+
public OwnedParrotFinder(DataBaseConnection db) {
32+
this.db = db;
33+
}
34+
35+
public OwnedParrotGateWay findById(Integer id) throws SQLException {
36+
OwnedParrotGateWay ownedParrotGateWay = ParrotRegistry.getOwnedParrot(id);
37+
38+
if (ownedParrotGateWay != null) {
39+
return ownedParrotGateWay;
40+
}
41+
42+
if (db == null) {
43+
db = new DataBaseConnection();
44+
}
45+
try (Connection connection = db.getConnection()) {
46+
PreparedStatement getStmt;
47+
48+
if (connection != null) {
49+
50+
getStmt = connection.prepareStatement(FIND_BY_ID);
51+
getStmt.setInt(1, id);
52+
53+
ResultSet rs = getStmt.executeQuery();
54+
55+
if (rs != null && rs.next()) {
56+
ownedParrotGateWay = new OwnedParrotGateWay(rs.getInt(OWNED_PARROT_ID),
57+
rs.getInt(PARROT_TYPE_ID),
58+
rs.getString(PARROT_NAME),
59+
rs.getInt(PARROT_AGE),
60+
rs.getString(COLOR),
61+
rs.getBoolean(TAMED));
62+
ParrotRegistry.addOwnedParrot(ownedParrotGateWay);
63+
db.closeConnection(connection);
64+
return ownedParrotGateWay;
65+
}
66+
}
67+
}
68+
return null;
69+
}
70+
71+
public List<OwnedParrotGateWay> findAll() throws SQLException {
72+
73+
if (db == null) {
74+
db = new DataBaseConnection();
75+
}
76+
Connection connection = db.getConnection();
77+
PreparedStatement getSizeStmt = null;
78+
PreparedStatement getAllOwnedParrotsStmt = null;
79+
80+
List<OwnedParrotGateWay> ownedParrotGateWayList = new ArrayList<>();
81+
82+
if (connection != null) {
83+
84+
getSizeStmt = connection.prepareStatement(COUNT_FROM_OWNED_PARROT);
85+
ResultSet rs = getSizeStmt.executeQuery();
86+
87+
if (rs != null && rs.next()) {
88+
int numberOfOwnedParrots = rs.getInt("count");
89+
if (ParrotRegistry.getParrotRegistrySize() == numberOfOwnedParrots) {
90+
ownedParrotGateWayList = ParrotRegistry.getAllOwnedParrotsInRegistry();
91+
} else {
92+
getAllOwnedParrotsStmt = connection.prepareStatement(FIND_ALL);
93+
ResultSet ownedParrotsResult = getAllOwnedParrotsStmt.executeQuery();
94+
95+
if (ownedParrotsResult != null) {
96+
while (ownedParrotsResult.next()) {
97+
OwnedParrotGateWay ownedParrotGateWay = new OwnedParrotGateWay(rs.getInt(OWNED_PARROT_ID),
98+
rs.getInt(PARROT_TYPE_ID),
99+
rs.getString(PARROT_NAME),
100+
rs.getInt(PARROT_AGE),
101+
rs.getString(COLOR),
102+
rs.getBoolean(TAMED));
103+
ParrotRegistry.addOwnedParrot(ownedParrotGateWay);
104+
}
105+
db.closeConnection(connection);
106+
ownedParrotGateWayList = ParrotRegistry.getAllOwnedParrotsInRegistry();
107+
}
108+
}
109+
}
110+
}
111+
112+
return ownedParrotGateWayList;
113+
}
114+
115+
}

0 commit comments

Comments
 (0)