Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ashish Trivedi
2020-08-10 13:01:30 +05:30
417 changed files with 7034 additions and 3073 deletions

View File

@ -1,30 +1,26 @@
---
layout: pattern
title: Transaction script
title: Transaction Script
folder: transaction-script
permalink: /patterns/transaction-script/
categories: Domain logic
categories: Behavioral
tags:
- Data access
---
## Intent
Transaction script(TS) is mainly used in small applications where nothing complex is done and bigger architecture's are not needed.
Transaction Script organizes business logic by procedures where each procedure handles a single request from the presentation.
## Explanation
Real world example
> Your need is to be able to book a hotel room and also be able to cancel that booking.
>
> You need to create a hotel room booking system. Since the requirements are quite simple we intend to use the Transaction Script pattern here.
In plain words
> All logic related to booking a hotel room like checking room availability,
> calculate rates and update the database is done inside a single transaction script.
> Similar procedure is also needed for cancelling a room booking and all
> that logic will be in another transaction script.
> Transaction Script organizes business logic into transactions that the system needs to carry out.
Programmatic example
The Hotel class takes care of booking and cancelling a room in a hotel.
The `Hotel` class takes care of booking and cancelling room reservations.
```java
public class Hotel {
@ -76,7 +72,7 @@ public class Hotel {
}
```
This class has two methods, one for booking and cancelling a room respectively.
The `Hotel` class has two methods, one for booking and cancelling a room respectively. Each one of them handles a single transaction in the system, making `Hotel` implement the Transaction Script pattern.
```
public void bookRoom(int roomNumber);
@ -94,8 +90,7 @@ if booked then calculates the refund amount and updates the database using the D
![alt text](./etc/transaction-script.png "Transaction script model")
## Applicability
Use the transaction script model when the application has only a small amount of logic and that
logic won't be extended in the future.
Use the Transaction Script pattern when the application has only a small amount of logic and that logic won't be extended in the future.
## Consequences
* As the business logic gets more complicated,

View File

@ -23,7 +23,6 @@
package com.ashishtrivedi16.transactionscript;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.h2.jdbcx.JdbcDataSource;
@ -51,8 +50,8 @@ public class TransactionScriptApp {
addRooms(dao);
getRoomStatus(dao);
Hotel hotel = new Hotel(dao);
var hotel = new Hotel(dao);
hotel.bookRoom(1);
hotel.bookRoom(2);
@ -77,7 +76,7 @@ public class TransactionScriptApp {
}
}
private static void deleteSchema(DataSource dataSource) throws SQLException {
private static void deleteSchema(DataSource dataSource) throws java.sql.SQLException {
try (var connection = dataSource.getConnection();
var statement = connection.createStatement()) {
statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);
@ -89,7 +88,7 @@ public class TransactionScriptApp {
var statement = connection.createStatement()) {
statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);
} catch (Exception e) {
throw new CustomException(e.getMessage(), e);
throw new SqlException(e.getMessage(), e);
}
}
@ -99,7 +98,7 @@ public class TransactionScriptApp {
* @return h2 datasource
*/
private static DataSource createDataSource() {
JdbcDataSource dataSource = new JdbcDataSource();
var dataSource = new JdbcDataSource();
dataSource.setUrl(H2_DB_URL);
return dataSource;
}

View File

@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
public class Hotel {
private static final Logger LOGGER = LoggerFactory.getLogger(TransactionScriptApp.class);
private HotelDaoImpl hotelDao;
private final HotelDaoImpl hotelDao;
public Hotel(HotelDaoImpl hotelDao) {
this.hotelDao = hotelDao;
@ -44,7 +44,7 @@ public class Hotel {
*/
public void bookRoom(int roomNumber) throws Exception {
Optional<Room> room = hotelDao.getById(roomNumber);
var room = hotelDao.getById(roomNumber);
if (room.isEmpty()) {
throw new Exception("Room number: " + roomNumber + " does not exist");
@ -52,7 +52,7 @@ public class Hotel {
if (room.get().isBooked()) {
throw new Exception("Room already booked!");
} else {
Room updateRoomBooking = room.get();
var updateRoomBooking = room.get();
updateRoomBooking.setBooked(true);
hotelDao.update(updateRoomBooking);
}
@ -66,14 +66,14 @@ public class Hotel {
* @throws Exception if any error
*/
public void cancelRoomBooking(int roomNumber) throws Exception {
Optional<Room> room = hotelDao.getById(roomNumber);
var room = hotelDao.getById(roomNumber);
if (room.isEmpty()) {
throw new Exception("Room number: " + roomNumber + " does not exist");
} else {
if (room.get().isBooked()) {
Room updateRoomBooking = room.get();
var updateRoomBooking = room.get();
updateRoomBooking.setBooked(false);
int refundAmount = updateRoomBooking.getPrice();
hotelDao.update(updateRoomBooking);

View File

@ -26,7 +26,6 @@ package com.ashishtrivedi16.transactionscript;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Optional;
import java.util.Spliterator;
import java.util.Spliterators;
@ -48,7 +47,7 @@ public class HotelDaoImpl implements HotelDao {
try {
var connection = getConnection();
var statement = connection.prepareStatement("SELECT * FROM ROOMS");
ResultSet resultSet = statement.executeQuery(); // NOSONAR
var resultSet = statement.executeQuery(); // NOSONAR
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Room>(Long.MAX_VALUE,
Spliterator.ORDERED) {
@ -60,7 +59,7 @@ public class HotelDaoImpl implements HotelDao {
}
action.accept(createRoom(resultSet));
return true;
} catch (SQLException e) {
} catch (Exception e) {
throw new RuntimeException(e); // NOSONAR
}
}
@ -71,8 +70,8 @@ public class HotelDaoImpl implements HotelDao {
e.printStackTrace();
}
});
} catch (SQLException e) {
throw new CustomException(e.getMessage(), e);
} catch (Exception e) {
throw new SqlException(e.getMessage(), e);
}
}
@ -90,8 +89,8 @@ public class HotelDaoImpl implements HotelDao {
} else {
return Optional.empty();
}
} catch (SQLException ex) {
throw new CustomException(ex.getMessage(), ex);
} catch (Exception ex) {
throw new SqlException(ex.getMessage(), ex);
} finally {
if (resultSet != null) {
resultSet.close();
@ -113,8 +112,8 @@ public class HotelDaoImpl implements HotelDao {
statement.setBoolean(4, room.isBooked());
statement.execute();
return true;
} catch (SQLException ex) {
throw new CustomException(ex.getMessage(), ex);
} catch (Exception ex) {
throw new SqlException(ex.getMessage(), ex);
}
}
@ -130,8 +129,8 @@ public class HotelDaoImpl implements HotelDao {
statement.setBoolean(3, room.isBooked());
statement.setInt(4, room.getId());
return statement.executeUpdate() > 0;
} catch (SQLException ex) {
throw new CustomException(ex.getMessage(), ex);
} catch (Exception ex) {
throw new SqlException(ex.getMessage(), ex);
}
}
@ -141,12 +140,12 @@ public class HotelDaoImpl implements HotelDao {
var statement = connection.prepareStatement("DELETE FROM ROOMS WHERE ID = ?")) {
statement.setInt(1, room.getId());
return statement.executeUpdate() > 0;
} catch (SQLException ex) {
throw new CustomException(ex.getMessage(), ex);
} catch (Exception ex) {
throw new SqlException(ex.getMessage(), ex);
}
}
private Connection getConnection() throws SQLException {
private Connection getConnection() throws Exception {
return dataSource.getConnection();
}
@ -156,12 +155,12 @@ public class HotelDaoImpl implements HotelDao {
resultSet.close();
statement.close();
connection.close();
} catch (SQLException e) {
throw new CustomException(e.getMessage(), e);
} catch (Exception e) {
throw new SqlException(e.getMessage(), e);
}
}
private Room createRoom(ResultSet resultSet) throws SQLException {
private Room createRoom(ResultSet resultSet) throws Exception {
return new Room(resultSet.getInt("ID"),
resultSet.getString("ROOM_TYPE"),
resultSet.getInt("PRICE"),

View File

@ -26,18 +26,18 @@ package com.ashishtrivedi16.transactionscript;
/**
* Custom exception.
*/
public class CustomException extends Exception {
public class SqlException extends Exception {
private static final long serialVersionUID = 1L;
public CustomException() {
public SqlException() {
}
public CustomException(String message) {
public SqlException(String message) {
super(message);
}
public CustomException(String message, Throwable cause) {
public SqlException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -28,7 +28,6 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@ -103,7 +102,7 @@ public class HotelTest {
}
private static void deleteSchema(DataSource dataSource) throws SQLException {
private static void deleteSchema(DataSource dataSource) throws java.sql.SQLException {
try (var connection = dataSource.getConnection();
var statement = connection.createStatement()) {
statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);
@ -115,7 +114,7 @@ public class HotelTest {
var statement = connection.createStatement()) {
statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);
} catch (Exception e) {
throw new CustomException(e.getMessage(), e);
throw new SqlException(e.getMessage(), e);
}
}