diff --git a/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/Column.java b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/Column.java new file mode 100644 index 0000000..d186d47 --- /dev/null +++ b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/Column.java @@ -0,0 +1,12 @@ +package ru.mipt.diht.students.nkarpachev.databaseservice; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Column { + String name() default ""; +} diff --git a/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/DatabaseService.java b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/DatabaseService.java new file mode 100644 index 0000000..5859f2a --- /dev/null +++ b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/DatabaseService.java @@ -0,0 +1,239 @@ +package ru.mipt.diht.students.nkarpachev.databaseservice; + +import java.lang.reflect.Type; +import java.sql.*; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.IllegalFormatCodePointException; +import java.util.LinkedList; +import java.util.List; + +import ru.mipt.diht.students.nkarpachev.databaseservice.Table; + +public class DatabaseService { + private String tableName; + private Field[] fields; + private String[] columns; + private Class dataType; + private int primaryKeyField; + + private static String databaseUrl = "jdbc:h2:~/myownminoorm"; + + private String getUnderscore(String source) { + StringBuilder answer = new StringBuilder(); + for (int i = 0; i < source.length(); i++) { + answer.append(source.charAt(i)); + if ((i < source.length() - 1) && Character.isUpperCase(source.charAt(i+1))); + } + return source.toLowerCase(); + } + + public DatabaseService(Class objectType) throws Exception { + constructTable(objectType); + } + + private void constructTable(Class dataType) { + if (!dataType.isAnnotationPresent(Table.class)) { + throw new IllegalArgumentException(); + } + if ((dataType.getAnnotation(Table.class).name()).equals("")) { + tableName = dataType.getSimpleName(); + } + else { + tableName = dataType.getAnnotation(Table.class).name(); + } + + List columnNames = new ArrayList<>(); + List fieldNames = new ArrayList<>(); + int currentFieldNum = 0; + for (Field currentField : dataType.getFields()) { + String columnName = new String(); + if (!currentField.isAnnotationPresent(Column.class)) { + throw new IllegalArgumentException(); + } else { + + columnName = currentField.getAnnotation(Column.class).name() ; + if (currentField.isAnnotationPresent(PrimaryKey.class)) { + if (primaryKeyField != -1) { + throw new IllegalArgumentException("Must be only 1 primary key"); + } + primaryKeyField = currentFieldNum; + } + if (columnName.equals("")) { + columnName = (getUnderscore(columnName)).toLowerCase(); + } + } + columnNames.add(columnName); + fieldNames.add(currentField); + currentFieldNum++; + } + + fields = new Field[fieldNames.size()]; + fields = fieldNames.toArray(fields); + + columns = new String[columnNames.size()]; + columns = columnNames.toArray(columns); + + } + + public void createTable() { + StringBuilder createQuery = new StringBuilder(); + createQuery.append("CREATE TABLE IF NOT EXISTS "); + createQuery.append(tableName); + createQuery.append("("); + for (int i = 0; i < fields.length; i++) { + if (i != 0) { + createQuery.append(", "); + } + createQuery.append(columns[i] + " " + TypeConverter.convertType(fields[i].getType())); + if (i == primaryKeyField) { + createQuery.append(" PRIMARY KEY"); + } + } + createQuery.append(");"); + + try (Connection connection = DriverManager.getConnection(databaseUrl)) { + connection.createStatement().execute(createQuery.toString()); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void dropTable() { + try (Connection connection = DriverManager.getConnection(databaseUrl)) { + connection.createStatement().execute("DROP TABLE IF EXISTS " + tableName); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void insert(T element) { + StringBuilder insertQuery = new StringBuilder(); + insertQuery.append("INSERT INTO "); + insertQuery.append(tableName); + insertQuery.append(" VALUES("); + + List values = new ArrayList<>(); + try { + for (Field field : fields) { + values.add(field.get(element)); + } + } catch (IllegalAccessException e) { + System.out.println(e.getMessage()); + } + + for (int i = 0; i < fields.length; i++) { + if (i != 0) { + insertQuery.append(", "); + } + insertQuery.append("?"); + } + insertQuery.append(")"); + Object[] valuesArray = new Object[values.size()]; + valuesArray = values.toArray(); + try (Connection connection = DriverManager.getConnection(databaseUrl)) { + try (PreparedStatement statement = connection.prepareStatement(insertQuery.toString())) { + for (int i = 0; i < valuesArray.length; i++) { + statement.setObject(i + 1, valuesArray[i]); + } + statement.execute(); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + } + + public void update(T element) { + try { + if (delete(element)) { + insert(element); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + + } + + public boolean delete(T element) { + StringBuilder deleteQuery = new StringBuilder(); + deleteQuery.append("DELETE FROM "); + deleteQuery.append(tableName); + deleteQuery.append(" WHERE"); + deleteQuery.append(columns[primaryKeyField]); + deleteQuery.append("=?"); + + try (Connection connection = DriverManager.getConnection(databaseUrl)) { + try (PreparedStatement statement = connection.prepareStatement(deleteQuery.toString())) { + statement.setObject(1, fields[primaryKeyField].get(element)); + statement.execute(); + return (statement.executeUpdate() > 0); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + return false; + } + + public List queryById(K key) { + StringBuilder primaryKeyQuery = new StringBuilder(); + primaryKeyQuery.append("SELECT * FROM "); + primaryKeyQuery.append(tableName); + primaryKeyQuery.append(" WHERE "); + String primaryName = columns[primaryKeyField]; + primaryKeyQuery.append(primaryName); + primaryKeyQuery.append("=?"); + + try (Connection connection = DriverManager.getConnection(databaseUrl)) { + PreparedStatement statement = connection.prepareStatement(primaryKeyQuery.toString()); + statement.setObject(1, key); + ResultSet resultSet = statement.executeQuery(); + return makeList(resultSet); + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + return null; + } + + public List queryAll() { + StringBuilder selectAllQuery = new StringBuilder(); + selectAllQuery.append("SELECT * FROM "); + selectAllQuery.append(tableName); + + try (Connection connection = DriverManager.getConnection(databaseUrl)) { + PreparedStatement statement = connection.prepareStatement(selectAllQuery.toString()); + ResultSet queryResult = statement.executeQuery(); + return makeList(queryResult); + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + return null; + } + + private List makeList(ResultSet set) { + try { + List answer = new LinkedList<>(); + while (set.next()) { + T entity = dataType.newInstance(); + for (int i = 0; i < fields.length; i++) { + fields[i].setAccessible(true); + String fieldName = columns[i]; + if (fieldName == null) { + continue; + } + fields[i].set(entity, set.getObject(fieldName)); + } + answer.add(entity); + } + return answer; + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + return null; + } +} diff --git a/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/PrimaryKey.java b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/PrimaryKey.java new file mode 100644 index 0000000..3fbdb10 --- /dev/null +++ b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/PrimaryKey.java @@ -0,0 +1,11 @@ +package ru.mipt.diht.students.nkarpachev.databaseservice; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface PrimaryKey { +} diff --git a/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/Table.java b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/Table.java new file mode 100644 index 0000000..9bbe38e --- /dev/null +++ b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/Table.java @@ -0,0 +1,9 @@ +package ru.mipt.diht.students.nkarpachev.databaseservice; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Table { + String name() default ""; +} diff --git a/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/TypeConverter.java b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/TypeConverter.java new file mode 100644 index 0000000..dac4f06 --- /dev/null +++ b/projects/nkarpachev/src/main/java/ru/mipt/diht/students/nkarpachev/databaseservice/TypeConverter.java @@ -0,0 +1,48 @@ +package ru.mipt.diht.students.nkarpachev.databaseservice; + +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.UUID; + +public class TypeConverter { + + private static HashMap h2ClassTypes; + private static HashMap h2PrimeTypes; + + public static void makeTypeMatch() { + h2PrimeTypes = new HashMap<>(); + h2PrimeTypes.put("int", "INTEGER"); + h2PrimeTypes.put("boolean", "BOOLEAN"); + h2PrimeTypes.put("byte", "INTEGER"); + h2PrimeTypes.put("short", "INTEGER"); + h2PrimeTypes.put("long", "BIGINT"); + h2PrimeTypes.put("float", "FLOAT"); + h2PrimeTypes.put("double", "DOUBLE"); + + h2ClassTypes = new HashMap<>(); + h2ClassTypes.put(Integer.class, "INTEGER"); + h2ClassTypes.put(Boolean.class, "BOOLEAN"); + h2ClassTypes.put(Byte.class, "TINYINT"); + h2ClassTypes.put(Short.class, "SMALLINT"); + h2ClassTypes.put(Long.class, "BIGINT"); + h2ClassTypes.put(Double.class, "DOUBLE"); + h2ClassTypes.put(Float.class, "FLOAT"); + h2ClassTypes.put(Time.class, "TIME"); + h2ClassTypes.put(Date.class, "DATE"); + h2ClassTypes.put(Timestamp.class, "TIMESTAMP"); + h2ClassTypes.put(Character.class, "CHAR"); + h2ClassTypes.put(String.class, "VARCHAR(2000)"); + h2ClassTypes.put(UUID.class, "UUID"); + } + + public static String convertType(Class type) { + if (h2PrimeTypes.containsKey(type.toString())) { + return h2PrimeTypes.get(type.toString()); + } else if (h2ClassTypes.containsKey(type)) { + return h2ClassTypes.get(type); + } + return null; + } +}