diff --git a/transaction-script/pom.xml b/transaction-script/pom.xml index 1d3c7a8a9..3fc06ca51 100644 --- a/transaction-script/pom.xml +++ b/transaction-script/pom.xml @@ -11,5 +11,18 @@ transaction-script + + + com.h2database + h2 + 1.4.200 + test + + + com.h2database + h2 + + + diff --git a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/Hotel.java b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/Hotel.java index ec9f8afee..d991f0f42 100644 --- a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/Hotel.java +++ b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/Hotel.java @@ -4,21 +4,22 @@ public class Hotel { public void bookRoom(int roomNumber) { /* - TODO - -> Check if room is available - -> Calculate price - -> Book the room - -> Commit transaction + TODO + -> Check if room is available + -> Calculate price + -> Book the room + -> Commit transaction */ } public void cancelRoomBooking(int roomNumber) { /* + TODO - -> Check if room is booked - -> Calculate refund price - -> Cancel the room booking - -> Commit transaction + -> Check if room is booked + -> Calculate refund price + -> Cancel the room booking + -> Commit transaction */ } } diff --git a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/Room.java b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/Room.java new file mode 100644 index 000000000..bf8b1ccf7 --- /dev/null +++ b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/Room.java @@ -0,0 +1,80 @@ +package com.ashishtrivedi16.transactionscript; + +public class Room { + + private int id; + private String roomType; + private int price; + private boolean booked; + + public Room(int id, String roomType, int price, boolean booked) { + this.id = id; + this.roomType = roomType; + this.price = price; + this.booked = booked; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getRoomType() { + return roomType; + } + + public void setRoomType(String roomType) { + this.roomType = roomType; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + public boolean isBooked() { + return booked; + } + + public void setBooked(boolean booked) { + this.booked = booked; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Room room = (Room) o; + + if (id != room.id) return false; + if (price != room.price) return false; + if (booked != room.booked) return false; + return roomType == room.roomType; + } + + @Override + public int hashCode() { + int result = id; + result = 31 * result + roomType.hashCode(); + result = 31 * result + price; + result = 31 * result + (booked ? 1 : 0); + return result; + } + + @Override + public String toString() { + return "Room{" + + "id=" + id + + ", roomType=" + roomType + + ", price=" + price + + ", booked=" + booked + + '}'; + } +} diff --git a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/TransactionScriptApp.java b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/TransactionScriptApp.java index 17f8f55f5..df29c6d09 100644 --- a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/TransactionScriptApp.java +++ b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/TransactionScriptApp.java @@ -1,14 +1,92 @@ package com.ashishtrivedi16.transactionscript; +import com.ashishtrivedi16.transactionscript.db.HotelDAOImpl; +import com.ashishtrivedi16.transactionscript.db.RoomSchemaSql; +import org.h2.jdbcx.JdbcDataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.sql.DataSource; +import java.sql.SQLException; +import java.util.List; + public class TransactionScriptApp { + private static final String H2_DB_URL = "jdbc:h2:~/test"; private static final Logger LOGGER = LoggerFactory.getLogger(TransactionScriptApp.class); + private static final String ALL_ROOMS = "customerDao.getAllRooms(): "; - public static void main(String[] args) { - LOGGER.info("Hello, World!"); + public static void main(String[] args) throws Exception { + + /* + TODO + -> Create in memory database and some sample tables for demo + */ + final var dataSource = createDataSource(); + createSchema(dataSource); + final var DAO = new HotelDAOImpl(dataSource); + try (var customerStream = DAO.getAll()) { + customerStream.forEach((customer) -> LOGGER.info(customer.toString())); + } + + deleteSchema(dataSource); } + + private static void deleteSchema(DataSource dataSource) throws SQLException { + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement()) { + statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL); + } + } + + private static void createSchema(DataSource dataSource) throws SQLException { + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement()) { + statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL); + } + } + + public static DataSource createDataSource() { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setUrl(H2_DB_URL); + return dataSource; + } + + private static void addRooms(HotelDAOImpl hotelDAO) throws Exception { + for (var room : generateSampleRooms()) { + hotelDAO.add(room); + } + } + + public static List generateSampleRooms() { + final var room1 = new Room(1, "Single", 50, false); + final var room2 = new Room(2, "Double", 80, false); + final var room3 = new Room(3, "Queen", 120, false); + final var room4 = new Room(4, "King", 150, false); + final var room5 = new Room(5, "Single", 50, false); + final var room6 = new Room(6, "Double", 80, false); + return List.of(room1, room2, room3, room4, room5, room6); + } + + private static void generate(final HotelDAOImpl hotelDAO) throws Exception { +// addRooms(hotelDAO); +// LOGGER.info(ALL_ROOMS); +// try (var customerStream = hotelDAO.getAll()) { +// customerStream.forEach((customer) -> LOGGER.info(customer.toString())); +// } +// LOGGER.info("hotelDAO.getCustomerById(2): " + hotelDAO.getById(2)); +// final var customer = new Room(4, "Dan", "Danson"); +// hotelDAO.add(customer); +// LOGGER.info(ALL_ROOMS + hotelDAO.getAll()); +// customer.setFirstName("Daniel"); +// customer.setLastName("Danielson"); +// hotelDAO.update(customer); +// LOGGER.info(ALL_ROOMS); +// try (var customerStream = hotelDAO.getAll()) { +// customerStream.forEach((cust) -> LOGGER.info(cust.toString())); +// } +// hotelDAO.delete(customer); +// LOGGER.info(ALL_ROOMS + hotelDAO.getAll()); + } } diff --git a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/CustomException.java b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/CustomException.java new file mode 100644 index 000000000..4f7e11d45 --- /dev/null +++ b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/CustomException.java @@ -0,0 +1,43 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.ashishtrivedi16.transactionscript.db; + +/** + * Custom exception. + */ +public class CustomException extends Exception { + + private static final long serialVersionUID = 1L; + + public CustomException() { + } + + public CustomException(String message) { + super(message); + } + + public CustomException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/HotelDAO.java b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/HotelDAO.java new file mode 100644 index 000000000..76b577f72 --- /dev/null +++ b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/HotelDAO.java @@ -0,0 +1,20 @@ +package com.ashishtrivedi16.transactionscript.db; + +import com.ashishtrivedi16.transactionscript.Room; + +import java.sql.SQLException; +import java.util.Optional; +import java.util.stream.Stream; + +public interface HotelDAO { + + public Stream getAll() throws Exception; + + public Optional getById(int id) throws Exception; + + public Boolean add(Room room) throws SQLException, Exception; + + public Boolean update(Room room) throws Exception; + + public Boolean delete(Room room) throws Exception; +} diff --git a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/HotelDAOImpl.java b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/HotelDAOImpl.java new file mode 100644 index 000000000..f4cfcc276 --- /dev/null +++ b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/HotelDAOImpl.java @@ -0,0 +1,151 @@ +package com.ashishtrivedi16.transactionscript.db; + +import com.ashishtrivedi16.transactionscript.Room; +import com.ashishtrivedi16.transactionscript.TransactionScriptApp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.sql.DataSource; +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; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class HotelDAOImpl implements HotelDAO { + + private static final Logger LOGGER = LoggerFactory.getLogger(TransactionScriptApp.class); + private final DataSource dataSource; + + public HotelDAOImpl(DataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + public Stream getAll() throws Exception { + try { + var connection = getConnection(); + var statement = connection.prepareStatement("SELECT * FROM ROOMS"); + ResultSet resultSet = statement.executeQuery(); // NOSONAR + return StreamSupport.stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED) { + + @Override + public boolean tryAdvance(Consumer action) { + try { + if (!resultSet.next()) { + return false; + } + action.accept(createRoom(resultSet)); + return true; + } catch (SQLException e) { + throw new RuntimeException(e); // NOSONAR + } + } + }, false).onClose(() -> { + try { + mutedClose(connection, statement, resultSet); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + } + + @Override + public Optional getById(int id) throws Exception { + ResultSet resultSet = null; + + try (var connection = getConnection(); + var statement = connection.prepareStatement("SELECT * FROM ROOMS WHERE ID = ?")) { + + statement.setInt(1, id); + resultSet = statement.executeQuery(); + if (resultSet.next()) { + return Optional.of(createRoom(resultSet)); + } else { + return Optional.empty(); + } + } catch (SQLException ex) { + throw new CustomException(ex.getMessage(), ex); + } finally { + if (resultSet != null) { + resultSet.close(); + } + } + } + + @Override + public Boolean add(Room room) throws Exception { + if (getById(room.getId()).isPresent()) { + return false; + } + + try (var connection = getConnection(); + var statement = connection.prepareStatement("INSERT INTO ROOMS VALUES (?,?,?)")) { + statement.setInt(1, room.getId()); + statement.setString(2, room.getRoomType()); + statement.setInt(3, room.getPrice()); + statement.setBoolean(4, room.isBooked()); + statement.execute(); + return true; + } catch (SQLException ex) { + throw new CustomException(ex.getMessage(), ex); + } + } + + @Override + public Boolean update(Room room) throws Exception { + try (var connection = getConnection(); + var statement = + connection + .prepareStatement("UPDATE ROOMS SET ROOM_TYPE = ?, PRICE = ?, BOOKED = ? WHERE ID = ?")) { + statement.setInt(1, room.getId()); + statement.setString(2, room.getRoomType()); + statement.setBoolean(3, room.isBooked()); + statement.setInt(4, room.getId()); + return statement.executeUpdate() > 0; + } catch (SQLException ex) { + throw new CustomException(ex.getMessage(), ex); + } + } + + @Override + public Boolean delete(Room room) throws Exception { + try (var connection = getConnection(); + var statement = connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) { + statement.setInt(1, room.getId()); + return statement.executeUpdate() > 0; + } catch (SQLException ex) { + throw new CustomException(ex.getMessage(), ex); + } + } + + private Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } + + private void mutedClose(Connection connection, PreparedStatement statement, ResultSet resultSet) throws Exception { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + } + + private Room createRoom(ResultSet resultSet) throws SQLException { + return new Room(resultSet.getInt("ID"), + resultSet.getString("ROOM_TYPE"), + resultSet.getInt("PRICE"), + resultSet.getBoolean("BOOKED")); + } +} diff --git a/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/RoomSchemaSql.java b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/RoomSchemaSql.java new file mode 100644 index 000000000..e883e50b9 --- /dev/null +++ b/transaction-script/src/main/java/com/ashishtrivedi16/transactionscript/db/RoomSchemaSql.java @@ -0,0 +1,39 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.ashishtrivedi16.transactionscript.db; + +/** + * Customer Schema SQL Class. + */ +public final class RoomSchemaSql { + + private RoomSchemaSql() { + } + + public static final String CREATE_SCHEMA_SQL = + "CREATE TABLE ROOMS (ID NUMBER, ROOM_TYPE VARCHAR(100), PRICE INT(100), BOOKED VARCHAR(100))"; + + public static final String DELETE_SCHEMA_SQL = "DROP TABLE ROOMS"; + +}