DatabaseTable.java 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. package db;
  2. import java.util.List;
  3. import java.lang.reflect.Field;
  4. import java.math.BigDecimal;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. import java.util.Optional;
  9. import java.util.logging.Logger;
  10. import db.annotation.DbTable;
  11. import db.mapper.DatabaseMapper;
  12. public abstract class DatabaseTable<T extends Persistable> {
  13. private static final Logger LOGGER = Logger.getLogger(DatabaseTable.class.getName());
  14. private Map<Long, T> cacheMap = new HashMap<>();
  15. public T get(T obj) {
  16. return getById(obj.getId());
  17. }
  18. public Optional<T> find(T obj) {
  19. return findById(obj.getId());
  20. }
  21. public T getById(long id) {
  22. if (cacheMap.containsKey(id)) {
  23. return cacheMap.get(id);
  24. }
  25. Optional<T> opt = getFromDbById(id);
  26. if(opt.isPresent()) {
  27. return cache(opt.get());
  28. }
  29. return null;
  30. }
  31. public Optional<T> findById(long id) {
  32. T obj = getById(id);
  33. if (obj == null) {
  34. return Optional.empty();
  35. }
  36. return Optional.of(obj);
  37. }
  38. public List<T> getByField(String fieldname, Object value) {
  39. List<T> list = getFromDbByField(fieldname, value);
  40. list.forEach(elt -> cache(elt));
  41. return list;
  42. }
  43. public List<T> getWhere(List<String> fields, List<Object> values) {
  44. List<T> list = getWhereFromDb(fields, values);
  45. list.forEach(elt -> cache(elt));
  46. return list;
  47. }
  48. public List<T> getAll() {
  49. List<T> list = getAllFromDb();
  50. list.forEach(elt -> cache(elt));
  51. return list;
  52. }
  53. public T refresh(long id) throws DatabaseException {
  54. if (!DatabaseProperties.getBool("cache")) {
  55. throw new DatabaseException("Cache is not enabled, can't refresh");
  56. }
  57. if (!cacheMap.containsKey(id)) {
  58. throw new DatabaseException("Entity is not load, can't refresh");
  59. }
  60. Optional<T> optObj = getFromDbById(id);
  61. if(!optObj.isPresent()) {
  62. throw new DatabaseException("Unable to find entity in the database");
  63. }
  64. return cache(optObj.get());
  65. }
  66. public T refresh(T obj) throws DatabaseException {
  67. return refresh(obj.getId());
  68. }
  69. public T save(T obj) {
  70. try {
  71. // Si le cache est activé on se base dessus
  72. if (DatabaseProperties.getBool("cache")) {
  73. if (cacheMap.containsKey(obj.getId())) {
  74. update(obj);
  75. } else {
  76. insert(obj);
  77. }
  78. }
  79. // Sinon on regarde en base
  80. else {
  81. if (findById(obj.getId()).isPresent()) {
  82. update(obj);
  83. } else {
  84. insert(obj);
  85. }
  86. }
  87. return cache(obj);
  88. } catch (DatabaseException e) {
  89. LOGGER.severe(e.getMessage());
  90. return null;
  91. }
  92. }
  93. public boolean del(long id) {
  94. try {
  95. // Suppr de la base
  96. delete(id);
  97. // Retire du cache
  98. remove(id);
  99. // TOut est ok
  100. return true;
  101. } catch (DatabaseException e) {
  102. LOGGER.severe(e.getMessage());
  103. return false;
  104. }
  105. }
  106. public boolean del(T obj) {
  107. return del(obj.getId());
  108. }
  109. protected T cache(T obj) {
  110. // Si l'objet à un id invalide
  111. if (obj.getId() <= 0) {
  112. return obj;
  113. }
  114. // Si le cache est actif
  115. if (DatabaseProperties.getBool("cache")) {
  116. if (cacheMap.containsKey(obj.getId())) {
  117. cacheMap.replace(obj.getId(), obj);
  118. } else {
  119. cacheMap.put(obj.getId(), obj);
  120. }
  121. }
  122. //System.out.println("Cache size: " + cacheMap.size());
  123. //cacheMap.forEach((key, val) -> System.out.println("Cache: " + key));
  124. return obj;
  125. }
  126. protected List<T> cache(List<T> list) {
  127. list.forEach(elt -> cache(elt));
  128. return list;
  129. }
  130. private void remove(long id) {
  131. if (cacheMap.containsKey(id)) {
  132. cacheMap.remove(id);
  133. }
  134. }
  135. private DbTable getDbTableAnnotation() {
  136. Class<?> clazz = this.getClass();
  137. // Recupération info anotation DbTable
  138. if (!clazz.isAnnotationPresent(DbTable.class)) {
  139. throw new IllegalStateException("Unable ton find DbTable annotation");
  140. }
  141. return clazz.getAnnotation(DbTable.class);
  142. }
  143. private Optional<T> getFromDbById(long id) {
  144. DbTable dbTable = getDbTableAnnotation();
  145. // Recupère l'id
  146. Field idField = DatabaseUtils.getIdField(dbTable.entity());
  147. if (idField == null) {
  148. throw new IllegalStateException("Unable to find id field");
  149. }
  150. // Requete sql
  151. SQLQueryBuilder sql = SQLQueryBuilder.selectQuery(dbTable.name());
  152. sql.add(DatabaseUtils.getDbField(idField), id);
  153. Optional<T> result = Database.query(sql.toString(), sql.getParams(), DatabaseMapper.objectMapper(dbTable));
  154. // Return
  155. return result;
  156. }
  157. private List<T> getFromDbByField(String fieldname, Object value) {
  158. DbTable dbTable = getDbTableAnnotation();
  159. // Requete sql
  160. SQLQueryBuilder sql = SQLQueryBuilder.selectQuery(dbTable.name());
  161. sql.add(fieldname, value);
  162. Optional<List<T>> result = Database.query(sql.toString(), sql.getParams(), DatabaseMapper.listMapper(dbTable));
  163. // Return
  164. if(result.isPresent()) {
  165. return result.get();
  166. }
  167. return new ArrayList<>();
  168. }
  169. private List<T> getWhereFromDb(List<String> where, List<Object> params) {
  170. DbTable dbTable = getDbTableAnnotation();
  171. // Requete sql
  172. SQLQueryBuilder sql = SQLQueryBuilder.selectQuery(dbTable.name());
  173. where.forEach(elt -> sql.add(elt));
  174. // Execution requete
  175. Optional<List<T>> result = Database.query(sql.toString(), params, DatabaseMapper.listMapper(dbTable));
  176. // Return
  177. if(result.isPresent()) {
  178. return result.get();
  179. }
  180. return new ArrayList<>();
  181. }
  182. private List<T> getAllFromDb() {
  183. DbTable dbTable = getDbTableAnnotation();
  184. // Requete sql
  185. SQLQueryBuilder sql = SQLQueryBuilder.selectQuery(dbTable.name());
  186. Optional<List<T>> result = Database.query(sql.toString(), DatabaseMapper.listMapper(dbTable));
  187. // Return
  188. if(result.isPresent()) {
  189. return result.get();
  190. }
  191. return new ArrayList<>();
  192. }
  193. private void insert(T obj) throws DatabaseException {
  194. DbTable dbTable = getDbTableAnnotation();
  195. // Récupération du champ id
  196. Field id = DatabaseUtils.getIdField(obj.getClass());
  197. if (id == null) {
  198. throw new IllegalStateException("Unable to find id field");
  199. }
  200. try {
  201. // Création requete SQL
  202. SQLQueryBuilder sql = SQLQueryBuilder.insertQuery(dbTable.name());
  203. for(Field field : obj.getClass().getFields()) {
  204. String dbField;
  205. if ((dbField = DatabaseUtils.getDbField(field)) == null || DatabaseUtils.isDbId(field)) {
  206. continue;
  207. }
  208. Object value = field.get(obj);
  209. // Si c'est un lien vers une autre entité
  210. if (value != null && DatabaseUtils.isDbLink(field)) {
  211. // Recup class gestion de la table pour sauvegarder l'objet avant de l'ajouter à la requete
  212. Persistable link = DatabaseUtils.getDbLinkObject(field, obj);
  213. DatabaseTable dt = DatabaseUtils.getDatabaseTable(field);
  214. dt.save(link);
  215. value = link.getId();
  216. }
  217. sql.add(dbField, value);
  218. }
  219. // Execution de la requete
  220. String dbIdName = DatabaseUtils.getDbField(id);
  221. String attrIdName = id.getName();
  222. Map<String, Object> newId = Database.insert(sql.toString(), sql.getParams(), new String[]{dbIdName});
  223. if (newId.isEmpty()) {
  224. throw new DatabaseException("Unable to save data");
  225. }
  226. // Récupération de l'id
  227. Object val = newId.get(dbIdName);
  228. if (val instanceof BigDecimal) {
  229. BigDecimal b = (BigDecimal) val;
  230. obj.getClass().getField(attrIdName).set(obj, b.longValue());
  231. } else {
  232. obj.getClass().getField(attrIdName).set(obj, val);
  233. }
  234. } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
  235. throw new IllegalStateException("Unable to save data", e);
  236. }
  237. }
  238. private void update(T obj) throws DatabaseException {
  239. DbTable dbTable = getDbTableAnnotation();
  240. // Récupération du champ id
  241. Field id = DatabaseUtils.getIdField(obj.getClass());
  242. if (id == null) {
  243. throw new IllegalStateException("Unable to find id field");
  244. }
  245. try {
  246. // Création requete SQL
  247. SQLQueryBuilder sql = SQLQueryBuilder.updateQuery(dbTable.name());
  248. for(Field field : obj.getClass().getFields()) {
  249. String dbField;
  250. if ((dbField = DatabaseUtils.getDbField(field)) == null || DatabaseUtils.isDbId(field)) {
  251. continue;
  252. }
  253. Object value = field.get(obj);
  254. // Si c'est un lien vers une autre entité
  255. if (value != null && DatabaseUtils.isDbLink(field)) {
  256. // Recup class gestion de la table pour sauvegarder l'objet avant de l'ajouter à la requete
  257. Persistable link = DatabaseUtils.getDbLinkObject(field, obj);
  258. DatabaseTable dt = DatabaseUtils.getDatabaseTable(field);
  259. dt.save(link);
  260. value = link.getId();
  261. }
  262. sql.add(dbField, value);
  263. }
  264. // Ajoute l'id
  265. sql.addId(DatabaseUtils.getDbField(id), id.get(obj));
  266. // Execution de la requete
  267. if(!Database.execute(sql.toString(), sql.getParams())) {
  268. throw new DatabaseException("Unable to save data");
  269. }
  270. } catch (IllegalArgumentException | IllegalAccessException | SecurityException e) {
  271. throw new IllegalStateException("Unable to save data", e);
  272. }
  273. }
  274. private void delete(long id) throws DatabaseException {
  275. DbTable dbTable = getDbTableAnnotation();
  276. // Récupération du champ id
  277. Field idField = DatabaseUtils.getIdField(dbTable.entity());
  278. if (idField == null) {
  279. throw new IllegalStateException("Unable to find id field");
  280. }
  281. // Création requete SQL
  282. SQLQueryBuilder sql = SQLQueryBuilder.deleteQuery(dbTable.name());
  283. sql.addId(DatabaseUtils.getDbField(idField), id);
  284. // Execution de la requete
  285. if (!Database.execute(sql.toString(), sql.getParams())) {
  286. throw new DatabaseException("Unable to delete data");
  287. }
  288. }
  289. }