package Common.Database; import Common.Constants; import Common.Global; import Common.Utils.Utils; import Repository.RepositoryRefuseException; import Common.Passes.PassCode_2021; import java.io.File; import java.util.LinkedHashMap; import java.util.Vector; //самый общий интерфейс базы данных, независимо от реализации. public abstract class Database { //------------------------------ public LinkedHashMap, DBTable> tables = new LinkedHashMap<>(); //таблицы protected File file = null; public Database(File file_in) { file = file_in; } public File getFile() { return file; } public void setFile(File file_in) { file = file_in; } // public void Connect() throws Exception { // UI.Print(DebugPrintLevel.Database, "соединение с базой данных " + file.getAbsolutePath()); connect(); } public void prepareTablesStatements() throws Exception { } public void Disconnect() throws Exception { // UI.Print(DebugPrintLevel.Database, "закрытие соединения с базой данных " + file.getAbsolutePath()); disconnect(); } public void BeginTransaction() throws Exception { // UI.Print(DebugPrintLevel.Database, "BEGIN TRANSACTION:"); beginTransaction(); } public void Commit() throws Exception { // UI.Print(DebugPrintLevel.Database, "COMMIT"); commit(); } public void CreateAllTables() throws Exception { BeginTransaction(); initAllTables(); // все добавления новых таблиц - туть. for (DBTable table : tables.values()) { CreateTable(table); table.setDb(this); } Commit(); } //схема как с проходами. в методе initAllTables добавляем все таблицы через уникальные конструкторы public void addTable(DBTable table) { tables.put(table.d, table); } public void Synchronize() throws Exception { BeginTransaction(); for (DBTable table : tables.values()) LoadAll(table); Init(); //перегружаемая часть синхронизации. Commit(); } public void LoadAllTablesWithoutInit() throws Exception { BeginTransaction(); for (DBTable table : tables.values()) LoadAll(table); Commit(); } public void LoadAll(DBTable table) throws Exception { table.Data.clear(); loadAll(table); } public DBObject Insert(DBObject o) throws Exception { DBTable table = tables.get(o.getClass()); insert(table, o); table.Data.put(o.getPK(), o); return o; } public DBObject InsertWithCheck(DBObject o) throws Exception { DBTable table = tables.get(o.getClass()); if (!table.Data.containsKey(o.getPK())) { insert(table, o); table.Data.put(o.getPK(), o); } else throw new RepositoryRefuseException("Таблица " + Utils.Brackets(table.Name) + " уже содержит объект с ключом " + Utils.Brackets(o.getPK().toString())); return o; } public DBObject InsertWithCheck_(DBObject o) throws Exception { DBTable table = tables.get(o.getClass()); if (!table.Data.containsKey(o.getPK())) { insert(table, o); table.Data.put(o.getPK(), o); return o; } return null; } // не работает с автоинкрементом. public DBObject UpdateWithCheck(DBObject to_update) throws Exception { DBTable table = tables.get(to_update.getClass()); if (table.Data.containsKey(to_update.getPK())) { DBObject o = (DBObject) table.Data.get(to_update.getPK()); o.SynchronizeFields(to_update); update(table, o); return o; } else { insert(table, to_update); table.Data.put(to_update.getPK(), to_update); return to_update; } } public DBObject DeleteWithCheck(DBObject to_delete) throws Exception { DBTable table = tables.get(to_delete.getClass()); if (table.Data.containsKey(to_delete.getPK())) { DBObject o = (DBObject) table.Data.get(to_delete.getPK()); delete(table, o); table.Data.remove(o.getPK()); return o; } else throw new RepositoryRefuseException("Таблица " + Utils.Brackets(table.Name) + " не содержит объект с ключом " + Utils.Brackets(to_delete.getPK().toString())); } public DBObject DeleteByPK(Class object_class, Object key) throws Exception { DBTable table = tables.get(object_class); if (table.Data.containsKey(key)) { DBObject o = (DBObject) table.Data.get(key); delete(table, o); table.Data.remove(key); return o; } else throw new RepositoryRefuseException("Таблица " + Utils.Brackets(table.Name) + " не содержит объект с ключом " + Utils.Brackets(key.toString())); } // не работает с автоинкрементом. public DBObject getObjectCopyByPK(Class table_class, Object pk) throws Exception { DBTable table = tables.get(table_class); Object res_ = table_class.newInstance(); DBObject res = (DBObject) res_; if (table.Data.containsKey(pk)) { DBObject original = (DBObject) table.Data.get(pk); res.SynchronizeFields(original); } else { table_class.getField(table.getPKName()).set(res, pk); //инче просто синхроним пк. и вставляем insert(table, res); } return res; } public boolean checkObjectExistense(Class table_class, Object pk) throws Exception { DBTable table = tables.get(table_class); return table.containsKey(pk); } public Vector getObjectsCopies(Class table_class, Vector keys) { Vector res = new Vector<>(); DBTable table = tables.get(table_class); for (Object key : keys) if (table.containsKey(key)) res.add(table.Data.get(key)); return res; } public void Delete(DBObject o) throws Exception { DBTable table = tables.get(o.getClass()); delete(table, o); table.Data.remove(o.getPK()); } public void DeleteAll(Class c) throws Exception { DBTable table = tables.get(c); deleteAll(table); table.Data.clear(); } //не вполне обычный случай. подразумевается что поле объекта изменено //этот же метод закрепляет изменение в бд //в дальнейшем возможно сделать новое значение поля 2 параметром метода? public void Update(DBObject o) throws Exception { DBTable table = tables.get(o.getClass()); update(table, o); } public void ResetAI(Class c) throws Exception { resetAI(tables.get(c)); } // // public Vector getVectorByFK(O owner, Class fk_class) { Vector res = new Vector<>(); try { for (Object o : tables.get(fk_class).Data.values()) { if (fk_class.getField(owner.getFKName()).get(o).equals(owner.getPK())) res.add((DBObject) o); } } catch (Exception e) { Global.Log.PrintException(e); } return res; } public void DeleteByFK(DBObject master, Class fk_class) throws Exception { Vector to_delete = getVectorByFK(master, fk_class); BeginTransaction(); for (DBObject object : to_delete) Delete(object); Commit(); } //----------- public void DropByFK(DBObject master, Class fk_class) throws Exception { Vector to_drop = getVectorByFK(master, fk_class); BeginTransaction(); for (DBObject object : to_drop) { fk_class.getField(master.getFKName()).set(object, master.getEmptyFK()); Update(object); } Commit(); } public LinkedHashMap getMapByFK(O owner, Class fk_class, Class key_class) { LinkedHashMap res = new LinkedHashMap<>(); try { for (Object o : tables.get(fk_class).Data.values()) { F f = (F) o; if (fk_class.getField(owner.getFKName()).get(f).equals(owner.getPK())) res.put((K) f.getPK(), f); } } catch (Exception e) { Global.Log.PrintException(e); } return res; } public LinkedHashMap getMapByFKi(O owner, Class fk_class) { return getMapByFK(owner, fk_class, java.lang.Integer.class); } //- public Vector getVectorStringByFK(O owner, Class fk_class) { Vector res = new Vector<>(); try { for (Object o : tables.get(fk_class).Data.values()) { if (fk_class.getField(owner.getFKName()).get(o).equals(owner.getPK())) res.add(o.toString()); } } catch (Exception e) { Global.Log.PrintException(e); } return res; } //безопасное получение объекта по первичному ключу. public O getByPK(Class class_in, Object pk, Object undefined_pk) { return ((!pk.equals(undefined_pk)) && tables.get(class_in).Data.containsKey(pk)) ? (O) (tables.get(class_in).Data.get(pk)) : null; } public O getById(Class class_in, int pk) { return getByPK(class_in, pk, Constants.Nan); } public LinkedHashMap getByFKAndGroupBy(O owner, Class fk_class, String group_field, Class group_class) { LinkedHashMap res = new LinkedHashMap<>(); try { for (Object o : tables.get(fk_class).Data.values()) { F f = (F) o; if (fk_class.getField(owner.getFKName()).get(f).equals(owner.getPK())) res.put((G) (fk_class.getField(group_field).get(f)), f); } } catch (Exception e) { Global.Log.PrintException(e); } return res; } // // //- protected abstract void connect() throws Exception; protected abstract void disconnect() throws Exception; //- protected abstract void beginTransaction() throws Exception; protected abstract void commit() throws Exception; //- protected abstract boolean TableExists(DBTable table) throws Exception; protected abstract void CreateTable(DBTable table) throws Exception; protected abstract void loadAll(DBTable table) throws Exception; protected abstract void initAllTables() throws Exception; //перегружаемая часть синхронизации public void Init() throws Exception { } protected abstract void insert(DBTable table, DBObject o) throws Exception; protected abstract void delete(DBTable table, DBObject o) throws Exception; protected abstract void deleteAll(DBTable table) throws Exception; protected abstract void update(DBTable table, DBObject o) throws Exception; protected abstract void resetAI(DBTable table) throws Exception; //- public void SaveLastSelections() { for (DataSet dataSet : tables.values()) dataSet.SaveLastSelections(); } public void RestoreLastSelections() { for (DataSet dataSet : tables.values()) dataSet.RestoreLastSelections(); } //--- public abstract PassCode_2021 getSynchronizePassCode(); //если бд есть на сервере. }