| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- package db;
- import java.util.List;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.math.BigDecimal;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Optional;
- import db.annotation.DbField;
- import db.annotation.DbId;
- import db.annotation.DbTable;
- public abstract class Table<T extends Persistable> {
-
- private Map<Long, T> cacheMap = new HashMap<>();
-
- public T getById(long id) {
- if (cacheMap.containsKey(id)) {
- return cacheMap.get(id);
- }
- Optional<T> opt = getFromDbById(id);
- if(opt.isEmpty()) {
- return null;
- }
- return cache(opt.get());
- }
-
- public Optional<T> findById(long id) {
- T obj = getById(id);
- if (obj == null) {
- return Optional.empty();
- }
- return Optional.of(obj);
- }
-
- public List<T> getByField(String fieldname, Object value) {
- List<T> list = getFromDbByField(fieldname, value);
- list.forEach(elt -> cache(elt));
- return list;
- }
-
- public List<T> getWhere(List<String> fields, List<Object> values) {
- List<T> list = getWhereFromDb(fields, values);
- list.forEach(elt -> cache(elt));
- return list;
- }
-
- public List<T> getAll() {
- List<T> list = getAllFromDb();
- list.forEach(elt -> cache(elt));
- return list;
- }
-
- public T refresh(long id) {
- if (!cacheMap.containsKey(id)) {
- throw new IllegalArgumentException("Entity is not load, can't refresh");
- }
- Optional<T> optObj = getFromDbById(id);
- if(optObj.isEmpty()) {
- throw new IllegalStateException("Unable to find entity in the database");
- }
- T obj = optObj.get();
- cache(obj);
- return obj;
- }
-
- public T refresh(T obj) {
- return refresh(obj.getId());
- }
-
- public void save(T obj) {
- if (cacheMap.containsKey(obj.getId())) {
- update(obj);
- } else {
- insert(obj);
- }
- cache(obj);
- }
-
- public final void delete(long id) {
- DbTable dbTable = getDbTableAnnotation();
- // Cherche l'id
- String idField = null;
- for(Field field : dbTable.entity().getFields()) {
- if(!field.isAnnotationPresent(DbId.class)) {
- continue;
- }
- // Lecture du nom de l'id dans la base
- if(field.isAnnotationPresent(DbField.class)) {
- idField = field.getAnnotation(DbField.class).name();
- } else {
- throw new IllegalStateException("Unable to find DbField annotation on id");
- }
- }
- if (idField == null) {
- throw new IllegalStateException("Unable to find find DbField annotation");
- }
- // Requete SQL
- String sql = "Delete From " + dbTable.name() + " Where " + idField + " = ?";
- List<Object> params = new ArrayList<>();
- params.add(id);
- // Execution requete
- if (!Database.execute(sql, params)) {
- throw new IllegalStateException("Unable to delete data");
- }
- // Retire du cache
- remove(id);
- }
-
- public void delete(T obj) {
- delete(obj.getId());
- }
-
- private T cache(T obj) {
- if (cacheMap.containsKey(obj.getId())) {
- cacheMap.replace(obj.getId(), obj);
- } else {
- cacheMap.put(obj.getId(), obj);
- }
- //System.out.println("Cache size: " + cacheMap.size());
- //cacheMap.forEach((key, val) -> System.out.println("Cache: " + key));
- return obj;
- }
-
- private void remove(long id) {
- if (cacheMap.containsKey(id)) {
- cacheMap.remove(id);
- }
- }
-
- private DbTable getDbTableAnnotation() {
- Class<?> clazz = this.getClass();
- // Recupération info anotation DbTable
- if (!clazz.isAnnotationPresent(DbTable.class)) {
- throw new IllegalStateException("Unable ton find DbTable annotation");
- }
- return clazz.getAnnotation(DbTable.class);
- }
-
- private Optional<T> getFromDbById(long id) {
- DbTable dbTable = getDbTableAnnotation();
- // Cherche l'id
- String idField = null;
- for(Field field : dbTable.entity().getFields()) {
- if(!field.isAnnotationPresent(DbId.class)) {
- continue;
- }
- // Lecture du nom de l'id dans la base
- if(field.isAnnotationPresent(DbField.class)) {
- idField = field.getAnnotation(DbField.class).name();
- } else {
- throw new IllegalStateException("Unable to find DbField annotation on id");
- }
- }
- if (idField == null) {
- throw new IllegalStateException("Unable to find find DbField annotation");
- }
- // Requete sql
- String sql = "Select * From " + dbTable.name() + " Where " + idField + " = ?";
- List<Object> params = new ArrayList<>();
- params.add(id);
- Optional<T> result = Database.query(sql, params, rs -> {
- try {
- T obj = (T) dbTable.entity().getConstructor().newInstance();
- rs.next();
- for(Field field : dbTable.entity().getFields()) {
- if(!field.isAnnotationPresent(DbField.class)) {
- continue;
- }
- obj.getClass().getField(field.getName()).set(obj, rs.getObject(field.getAnnotation(DbField.class).name()));
- }
- return obj;
- } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | NoSuchFieldException | SQLException e) {
- throw new IllegalStateException("Unable to map value to the entity");
- }
- });
- // Return
- return result;
- }
-
- private List<T> getFromDbByField(String fieldname, Object value) {
- DbTable dbTable = getDbTableAnnotation();
- // Requete sql
- String sql = "Select * From " + dbTable.name() + " Where " + fieldname + " = ?";
- List<Object> params = new ArrayList<>();
- params.add(value);
- Optional<List<T>> result = Database.query(sql, params, rs -> {
- try {
- List<T> list = new ArrayList<>();
- while(rs.next()) {
- T obj = (T) dbTable.entity().getConstructor().newInstance();
- for(Field field : dbTable.entity().getFields()) {
- if(!field.isAnnotationPresent(DbField.class)) {
- continue;
- }
- obj.getClass().getField(field.getName()).set(obj, rs.getObject(field.getAnnotation(DbField.class).name()));
- }
- list.add(obj);
- }
- return list;
- } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | NoSuchFieldException | SQLException e) {
- throw new IllegalStateException("Unable to map value to the entity");
- }
- });
- // Return
- if(result.isEmpty()) {
- return new ArrayList<>();
- }
- return result.get();
- }
-
- private List<T> getWhereFromDb(List<String> where, List<Object> params) {
- DbTable dbTable = getDbTableAnnotation();
- // Requete sql
- StringBuilder sql = new StringBuilder();
- sql.append("Select * From " + dbTable.name() + "Where 1=1");
- where.forEach(elt -> sql.append(" And " + elt + " = ?"));
- // Execution requete
- Optional<List<T>> result = Database.query(sql.toString(), params, rs -> {
- try {
- List<T> list = new ArrayList<>();
- while(rs.next()) {
- T obj = (T) dbTable.entity().getConstructor().newInstance();
- for(Field field : dbTable.entity().getFields()) {
- if(!field.isAnnotationPresent(DbField.class)) {
- continue;
- }
- obj.getClass().getField(field.getName()).set(obj, rs.getObject(field.getAnnotation(DbField.class).name()));
- }
- list.add(obj);
- }
- return list;
- } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | NoSuchFieldException | SQLException e) {
- throw new IllegalStateException("Unable to map value to the entity");
- }
- });
- // Return
- if(result.isEmpty()) {
- return new ArrayList<>();
- }
- return result.get();
- }
-
- private List<T> getAllFromDb() {
- DbTable dbTable = getDbTableAnnotation();
- // Requete sql
- String sql = "Select * From " + dbTable.name();
- Optional<List<T>> result = Database.query(sql, rs -> {
- try {
- List<T> list = new ArrayList<>();
- while(rs.next()) {
- T obj = (T) dbTable.entity().getConstructor().newInstance();
- for(Field field : dbTable.entity().getFields()) {
- if(!field.isAnnotationPresent(DbField.class)) {
- continue;
- }
- obj.getClass().getField(field.getName()).set(obj, rs.getObject(field.getAnnotation(DbField.class).name()));
- }
- list.add(obj);
- }
- return list;
- } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | NoSuchFieldException | SQLException e) {
- throw new IllegalStateException("Unable to map value to the entity");
- }
- });
- // Return
- if(result.isEmpty()) {
- return new ArrayList<>();
- }
- return result.get();
- }
-
- private void insert(T obj) {
- DbTable dbTable = getDbTableAnnotation();
- // Requete SQL
- StringBuilder sql = new StringBuilder();
- StringBuilder values = new StringBuilder();
- String dbIdName = null; // Nom de l'id en base
- String attrIdName = null; // Nom de l'id dans la class
- List<Object> params = new ArrayList<>();
- sql.append("Insert Into " + dbTable.name() + "(");
- boolean first = true;
- try {
- for(Field field : obj.getClass().getFields()) {
- if (!field.isAnnotationPresent(DbField.class)) {
- continue;
- }
- // Cherche l'id
- if (dbIdName == null && field.isAnnotationPresent(DbId.class)) {
- dbIdName = field.getAnnotation(DbField.class).name();
- attrIdName = field.getName();
- continue;
- }
- // Recupere la valeur des autres attributs
- if (!first) {
- sql.append(",");
- values.append(",");
- }
- sql.append(field.getAnnotation(DbField.class).name());
- values.append("?");
- params.add(field.get(obj));
- first = false;
- }
- } catch (IllegalArgumentException | IllegalAccessException e) {
- throw new IllegalStateException("Unable to access to the attribute", e);
- }
- sql.append(") Values (");
- sql.append(values);
- sql.append(")");
- // Verif que l'on a bien le nom de l'id
- if(dbIdName == null) {
- throw new IllegalStateException("Unable to find id field");
- }
- // Execution de la requete
- Map<String, Object> newId = Database.insert(sql.toString(), params, new String[]{dbIdName});
- if (newId.isEmpty()) {
- throw new IllegalStateException("Unable to save data");
- }
- // Application nouvelle id
- Object val = newId.get(dbIdName);
- try {
- if (val instanceof BigDecimal) {
- BigDecimal b = (BigDecimal) val;
- obj.getClass().getField(attrIdName).set(obj, b.longValue());
- } else {
- obj.getClass().getField(attrIdName).set(obj, val);
- }
- } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
- throw new IllegalStateException("Unable to set id", e);
- }
- }
-
- private void update(T obj) {
- DbTable dbTable = getDbTableAnnotation();
- // Requete SQL
- StringBuilder sql = new StringBuilder();
- StringBuilder where = new StringBuilder();
- List<Object> params = new ArrayList<>();
- sql.append("Update " + dbTable.name() + " Set ");
- where.append(" Where ");
- boolean first = true;
- for (Field field : obj.getClass().getFields()) {
- try {
- if (!field.isAnnotationPresent(DbField.class)) {
- continue;
- }
- // Si c'est l'id
- if (field.isAnnotationPresent(DbId.class)) {
- where.append(field.getAnnotation(DbField.class).name() + " = ?");
- continue;
- }
- // Sinon ajoute dans le set
- if (!first) {
- sql.append(",");
- }
- sql.append(field.getAnnotation(DbField.class).name() + " = ?");
- params.add(field.get(obj));
- first = false;
- } catch (IllegalArgumentException | IllegalAccessException e) {
- throw new IllegalStateException("Unable to access to the attribute", e);
- }
- }
- sql.append(where);
- params.add(obj.getId());
- // Execution requete
- if(!Database.execute(sql.toString(), params)) {
- throw new IllegalStateException("Unable to save data");
- }
- }
- }
|