package de.hsel.itech.db; import de.hsel.itech.config.Configuration; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.json.JSONObject; import org.mariadb.jdbc.MariaDbPoolDataSource; import java.io.*; import java.net.URL; import java.nio.charset.Charset; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.AbstractMap; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * base class for everything regarding the database. * * @author Johannes Theiner * @version 0.1 * @since 0.1 */ public class Database { final String tableBook = "book"; final String tableAuthor = "author"; final String tableAuthorBook = "author_book"; final String tablePublisher = "publisher"; final String tableCategory = "category"; final String tableUser = "user"; final String tableUserAddress = "user_address"; final String tableAddress = "address"; final String tableCartBooks = "cart_books"; final String tableOrder = "`order`"; final String tableOrderBook = "order_book"; final String tablePaymentType = "payment_type"; final String tablePaymentPayPal = "payment_paypal"; final String tablePaymentCredit = "payment_credit"; final String tablePaymentDebit = "payment_debit"; final String tablePaymentInvoice = "payment_invoice"; final String tableUserPayment = "user_payment"; private AuthorDB authorDB; private BookDB bookDB; private CategoryDB categoryDB; private PublisherDB publisherDB; private UserDB userDB; private AddressDB addressDB; private ShoppingCartDB shoppingCartDB; private OrderDB orderDB; private PaymentDB paymentDB; private static Database instance; /** * Singleton for database access. * * @return {@link Database} */ public static Database getInstance() { if (instance == null) instance = new Database(); return instance; } private MariaDbPoolDataSource dataSource; /** * initializes connection pool and executes database setup. */ private Database() { Configuration config = Configuration.get(); dataSource = new MariaDbPoolDataSource("jdbc:mysql://" + config.getDatabase().getHostname() + ":" + config.getDatabase().getPort() + "/" + config.getDatabase().getDatabase() + "?useUnicode=true&characterEncoding=UTF-8&maxPoolSize=10&pool"); try { dataSource.setUser(config.getDatabase().getUsername()); dataSource.setPassword(config.getDatabase().getPassword()); dataSource.initialize(); Connection connection = getConnection(); assert connection != null; URL file = getClass().getClassLoader().getResource("database.sql"); assert file != null; try (BufferedReader br = new BufferedReader(new FileReader(file.getFile()))) { for (String line = br.readLine(); line != null; line = br.readLine()) { PreparedStatement statement = connection.prepareStatement(line); statement.executeUpdate(); statement.close(); } } catch (IOException e) { e.printStackTrace(); } finally { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } /** * gets connection from connection pool. * * @return {@link java.sql.Connection} */ @Nullable Connection getConnection() { try { return dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return null; } @Contract public BookDB book() { if(bookDB == null) bookDB = new BookDB(this); return bookDB; } @Contract public AuthorDB author() { if(authorDB == null) authorDB = new AuthorDB(this); return authorDB; } @Contract public CategoryDB category() { if (categoryDB == null) categoryDB = new CategoryDB(this); return categoryDB; } @Contract public PublisherDB publisher() { if(publisherDB == null) publisherDB = new PublisherDB(this); return publisherDB; } @Contract public UserDB user() { if(userDB == null) userDB = new UserDB(this); return userDB; } @Contract public AddressDB address() { if(addressDB == null) addressDB = new AddressDB(this); return addressDB; } @Contract public ShoppingCartDB shoppingCart() { if(shoppingCartDB == null) shoppingCartDB = new ShoppingCartDB(this); return shoppingCartDB; } @Contract public OrderDB order() { if(orderDB == null) orderDB = new OrderDB(this); return orderDB; } @Contract public PaymentDB payment() { if(paymentDB == null) paymentDB = new PaymentDB(this); return paymentDB; } /** * deletes entry from table. * * @param id database id * @param table table name * @return deletion count */ int delete(long id, @NotNull String table) { Connection connection = getConnection(); assert connection != null; int deleteCount = 0; try { PreparedStatement statement = connection.prepareStatement("DELETE FROM " + table + " WHERE id=?"); statement.setLong(1, id); deleteCount = +statement.executeUpdate(); } catch (SQLException ex) { ex.printStackTrace(); } return deleteCount; } /** * deletes entry from table. * * @param id id of entry to delete * @param table table to delete from * @param column column to delete id from * @return deletion count */ int delete(long id, @NotNull String table, @NotNull String column) { Connection connection = getConnection(); assert connection != null; int deleteCount = 0; try { PreparedStatement statement = connection.prepareStatement("DELETE FROM " + table + " WHERE " + column + "=?"); statement.setLong(1, id); deleteCount = +statement.executeUpdate(); } catch (SQLException ex) { ex.printStackTrace(); } return deleteCount; } /** * getAll all ids from specified table. * * @param table table * @return list of ids */ List getIds(@NotNull String table) { Map.Entry entry = getColumnsFromResultSet(table, "id"); assert entry != null; List ids = new ArrayList<>(); try { ResultSet rs = entry.getKey(); while (rs.next()) { ids.add(rs.getLong("id")); } entry.getValue().close(); } catch (SQLException ex) { ex.printStackTrace(); } return ids; } /** * gets specific entry from database. * * @param table table name * @param id id from database * @return {@link java.util.Map.Entry} */ @Nullable Map.Entry getResultSetById(@NotNull String table, long id) { return getResultSetByValue(table, "id", id); } @Nullable Map.Entry getResultSetByValue(@NotNull String table, @NotNull String column, long value) { Connection connection = getConnection(); try { assert connection != null; PreparedStatement statement = connection.prepareStatement("SELECT * FROM " + table + " WHERE " + column + " = ?"); statement.setLong(1, value); ResultSet resultSet = statement.executeQuery(); Map.Entry entry = null; while (resultSet.next()) { entry = new AbstractMap.SimpleEntry<>(resultSet, connection); } return entry; } catch (SQLException ex) { ex.printStackTrace(); } return null; } /** * gets specific entries from table. * * @param table table name * @param column column to match * @param id id all entries should reference * @return {@link java.util.Map.Entry} */ @Nullable Map.Entry getResultSetsById(@NotNull String table, @NotNull String column, long id) { Connection connection = getConnection(); try { assert connection != null; PreparedStatement statement = connection.prepareStatement("SELECT * FROM " + table + " WHERE " + column + " = ?"); statement.setLong(1, id); return getAllEntriesFromResultSet(connection, statement); } catch (SQLException ex) { ex.printStackTrace(); } return null; } /** * gets specific entries from table. * * @param table table name * @param column column to match * @return {@link java.util.Map.Entry} */ @Nullable Map.Entry getResultSetsByValue(@NotNull String table, @NotNull String column, @NotNull String value) { Connection connection = getConnection(); try { assert connection != null; PreparedStatement statement = connection.prepareStatement("SELECT * FROM " + table + " WHERE " + column + " = ?"); statement.setString(1, value); return getAllEntriesFromResultSet(connection, statement); } catch (SQLException ex) { ex.printStackTrace(); } return null; } /** * gets all specified columns from table. * * @param table table name * @param columns columns as String array * @return {@link java.util.Map.Entry} */ @Nullable private Map.Entry getColumnsFromResultSet(@NotNull String table, @NotNull String... columns) { Connection connection = getConnection(); try { assert connection != null; PreparedStatement statement = connection.prepareStatement("SELECT (" + String.join(",", columns) + ") FROM " + table); return getAllEntriesFromResultSet(connection, statement); } catch (SQLException ex) { ex.printStackTrace(); } return null; } /** * gets all entries contained in result set. * * @param connection Connection * @param statement query statement * @return {@link java.util.Map.Entry} */ @Nullable private Map.Entry getAllEntriesFromResultSet(@NotNull Connection connection, @NotNull PreparedStatement statement) { try { ResultSet resultSet = statement.executeQuery(); return new AbstractMap.SimpleEntry<>(resultSet, connection); } catch (SQLException ex) { ex.printStackTrace(); } return null; } @Nullable String getRandomImage() { try { try (InputStream is = new URL("https://api.unsplash.com/photos/random?client_id=" + Configuration.get().getUnsplash().getAccessKey()).openStream()) { BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8"))); StringBuilder sb = new StringBuilder(); int cp; while ((cp = rd.read()) != -1) { sb.append((char) cp); } JSONObject json = new JSONObject(sb.toString()); return json.getString("id"); } } catch (IOException e) { e.printStackTrace(); } return null; } }