Files
VisualSapfor/src/Common/Database/Database.java

287 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package Common.Database;
import Common.Constants;
import Common.Global;
import Common.Utils.Utils;
import Repository.RepositoryRefuseException;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.Vector;
//самый общий интерфейс базы данных, независимо от реализации.
public abstract class Database {
//------------------------------
public LinkedHashMap<Class<? extends DBObject>, 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;
}
//<editor-fold desc="Общая часть">
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 <K, D extends DBObject> void LoadAll(DBTable<K, D> 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<Object> getObjectsCopies(Class table_class, Vector<Object> keys) {
Vector<Object> 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<? extends DBObject> 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<? extends DBObject> c) throws Exception {
resetAI(tables.get(c));
}
//</editor-fold>
//<editor-fold desc="работа с внешними ключами">
public <O extends DBObject, F extends DBObject> Vector<DBObject> getVectorByFK(O owner, Class<F> fk_class) {
Vector<DBObject> 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 <F extends DBObject> void DeleteByFK(DBObject master, Class<F> fk_class) throws Exception {
Vector<DBObject> to_delete = getVectorByFK(master, fk_class);
BeginTransaction();
for (DBObject object : to_delete)
Delete(object);
Commit();
}
//-----------
public <F extends DBObject> void DropByFK(DBObject master, Class<F> fk_class) throws Exception {
Vector<DBObject> 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 <K, O extends DBObject, F extends DBObject> LinkedHashMap<K, F> getMapByFK(O owner, Class<F> fk_class, Class<K> key_class) {
LinkedHashMap<K, F> 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 <O extends DBObject, F extends iDBObject> LinkedHashMap<Integer, F> getMapByFKi(O owner, Class<F> fk_class) {
return getMapByFK(owner, fk_class, java.lang.Integer.class);
}
//-
public <O extends DBObject, F extends DBObject> Vector<String> getVectorStringByFK(O owner, Class<F> fk_class) {
Vector<String> 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 extends DBObject> O getByPK(Class<O> 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 extends iDBObject> O getById(Class<O> class_in, int pk) {
return getByPK(class_in, pk, Constants.Nan);
}
public <G, O extends DBObject, F extends DBObject> LinkedHashMap<G, F> getByFKAndGroupBy(O owner, Class<F> fk_class, String group_field, Class<G> group_class) {
LinkedHashMap<G, F> 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;
}
//</editor-fold>
//<editor-fold desc="Перегружаемая часть">
//-
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 <K, D extends DBObject> void loadAll(DBTable<K, D> 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();
}
}