Перенос.
This commit is contained in:
31
src/Common/Database/ColumnType.java
Normal file
31
src/Common/Database/ColumnType.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package Common.Database;
|
||||
public enum ColumnType {
|
||||
UNDEFINED,
|
||||
INT,
|
||||
LONG,
|
||||
DOUBLE,
|
||||
STRING;
|
||||
public static ColumnType valueOf(Class<?> type) {
|
||||
ColumnType res = UNDEFINED;
|
||||
try {
|
||||
res = valueOf(type.getSimpleName().toUpperCase());
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public String getSQLType() {
|
||||
String res = "";
|
||||
switch (this) {
|
||||
case INT:
|
||||
case LONG:
|
||||
res = "INTEGER";
|
||||
break;
|
||||
case DOUBLE:
|
||||
res = "REAL";
|
||||
break;
|
||||
case STRING:
|
||||
res = "VARCHAR";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
64
src/Common/Database/DBObject.java
Normal file
64
src/Common/Database/DBObject.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package Common.Database;
|
||||
import Common.UI.Selectable;
|
||||
import Common.Utils.Index;
|
||||
import Common.Utils.Utils;
|
||||
import com.sun.org.glassfish.gmbal.Description;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
public abstract class DBObject implements Selectable, Serializable {
|
||||
//<editor-fold desc="Selectable">
|
||||
@Description("IGNORE")
|
||||
private boolean selected = false;
|
||||
@Override
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
@Override
|
||||
public void select(boolean flag) {
|
||||
if (selected != flag) {
|
||||
selected = flag;
|
||||
Index counter = getSelectionCounter();
|
||||
if (Objects.nonNull(counter)) {
|
||||
if (selected) counter.Inc();
|
||||
else counter.Dec();
|
||||
}
|
||||
}
|
||||
}
|
||||
//</editor-fold>
|
||||
public Index getSelectionCounter() {
|
||||
return null;
|
||||
}
|
||||
public boolean isVisible() {
|
||||
return true;
|
||||
}
|
||||
public abstract Object getPK();
|
||||
public String getBDialogName() {
|
||||
return Utils.Brackets(getDialogName());
|
||||
}
|
||||
public String getDialogName() {
|
||||
return getPK().toString();
|
||||
}
|
||||
//статус. например завершенность багрепорта или состояние задачи на запуск. как правило обладает цветным шрифтом.
|
||||
//как объект будут называть по внешним ключам.
|
||||
public String getFKName() {
|
||||
return null;
|
||||
}
|
||||
public Object getEmptyFK() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return getBDialogName();
|
||||
}
|
||||
//---
|
||||
public void SynchronizeFields(DBObject src){
|
||||
selected = src.selected;
|
||||
}
|
||||
//------
|
||||
public DBObject(){}
|
||||
public DBObject(DBObject src){
|
||||
this.SynchronizeFields(src);
|
||||
}
|
||||
//---------
|
||||
}
|
||||
34
src/Common/Database/DBTable.java
Normal file
34
src/Common/Database/DBTable.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package Common.Database;
|
||||
import java.lang.reflect.Field;
|
||||
public abstract class DBTable<K, D extends DBObject> extends DataSet<K, D> {
|
||||
//-
|
||||
public DBTableColumn PK = null;
|
||||
private Database db = null; //база данных - владелец таблицы.
|
||||
public DBTable(Class<K> k_in, Class<D> d_in) {
|
||||
super(k_in, d_in);
|
||||
for (Field field : d.getFields()) {
|
||||
DBTableColumn column = new DBTableColumn(field);
|
||||
if ((!column.Ignore) && !columns.containsKey(column.Name)) {
|
||||
columns.put(column.Name, column);
|
||||
if (column.PrimaryKey) PK = column;
|
||||
}
|
||||
}
|
||||
}
|
||||
public Database getDb() {
|
||||
return db;
|
||||
}
|
||||
public void setDb(Database db_in) {
|
||||
db = db_in;
|
||||
}
|
||||
@Override
|
||||
public String getPKName() {
|
||||
return PK.Name;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder res = new StringBuilder(Name + "\n");
|
||||
for (DBTableColumn c : columns.values())
|
||||
res.append(c).append("\n");
|
||||
return res.toString();
|
||||
}
|
||||
}
|
||||
50
src/Common/Database/DBTableColumn.java
Normal file
50
src/Common/Database/DBTableColumn.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package Common.Database;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Vector;
|
||||
public class DBTableColumn {
|
||||
public String Name = "";
|
||||
public ColumnType type = ColumnType.UNDEFINED;
|
||||
public Vector<String> attributes = new Vector<String>();
|
||||
public boolean Ignore = false;
|
||||
public boolean PrimaryKey = false;
|
||||
public boolean AutoIncrement = false;
|
||||
public Object default_value = null;
|
||||
public DBTableColumn(Field field) {
|
||||
ExtractAttributes(field);
|
||||
PrimaryKey = attributes.contains("PRIMARY KEY");
|
||||
AutoIncrement = attributes.contains("AUTOINCREMENT");
|
||||
Name = field.getName();
|
||||
type = (field.getType().isEnum()) ? ColumnType.STRING : ColumnType.valueOf(field.getType());
|
||||
Ignore = ((Modifier.isStatic(field.getModifiers()) ||
|
||||
type.equals(ColumnType.UNDEFINED) ||
|
||||
attributes.contains("IGNORE")
|
||||
)
|
||||
);
|
||||
}
|
||||
public String QName() {
|
||||
return "\"" + Name + "\"";
|
||||
}
|
||||
public void ExtractAttributes(Field field) {
|
||||
attributes = new Vector<String>();
|
||||
Annotation[] annotations = field.getAnnotations();
|
||||
for (Annotation a : annotations) {
|
||||
String[] data = a.toString().split("value=");
|
||||
if (data.length > 1) {
|
||||
String[] attributes_ = data[1].split("[,\")]");
|
||||
for (String attribute : attributes_) {
|
||||
if (attribute.length() > 0)
|
||||
attributes.add(attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = QName() + " " + type.getSQLType();
|
||||
if (attributes.size() > 0)
|
||||
res += " " + String.join(" ", attributes);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
253
src/Common/Database/DataSet.java
Normal file
253
src/Common/Database/DataSet.java
Normal file
@@ -0,0 +1,253 @@
|
||||
package Common.Database;
|
||||
import Common.Current;
|
||||
import Common.UI.DataSetControlForm;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Common.UI.Tables.ColumnFilter;
|
||||
import Common.UI.UI;
|
||||
import Common.UI.Windows.Dialog.DBObjectDialog;
|
||||
import Common.UI.Windows.Dialog.DialogFields;
|
||||
import Common.Utils.TextLog;
|
||||
import Visual_DVM_2021.UI.Interface.FilterWindow;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Vector;
|
||||
import java.util.stream.Collectors;
|
||||
public class DataSet<K, D extends DBObject> extends DataSetAnchestor {
|
||||
//-
|
||||
public static LinkedHashMap<Class, Object> selections = new LinkedHashMap<>();
|
||||
//-
|
||||
public String Name;
|
||||
public Class<K> k; //класс первичного ключа.
|
||||
public Class<D> d; //класс объектов.
|
||||
public LinkedHashMap<K, D> Data = new LinkedHashMap<>(); //наполнение
|
||||
//-
|
||||
//<editor-fold desc="UI таблица">
|
||||
public DataSetControlForm ui_;
|
||||
protected FilterWindow f_ui;
|
||||
//</editor-fold>
|
||||
//-
|
||||
public LinkedHashMap<Integer, ColumnFilter> columnsFilters = new LinkedHashMap<>();
|
||||
public DataSet(Class<K> k_in, Class<D> d_in) {
|
||||
k = k_in;
|
||||
d = d_in;
|
||||
Name = d.getSimpleName();
|
||||
}
|
||||
public void mountUI(JPanel content_in) {
|
||||
UI.Clear(content_in);
|
||||
//-->
|
||||
ui_ = createUI();
|
||||
ui_.setContent(content_in);
|
||||
//-->
|
||||
if (UI.menuBars.containsKey(getClass())) {
|
||||
DataMenuBar bar = UI.menuBars.get(getClass());
|
||||
content_in.add(bar, BorderLayout.NORTH);
|
||||
setFilterUI(count -> UI.menuBars.get(getClass()).countLabel.setText(String.valueOf(count)));
|
||||
if (ui_.hasCheckBox())
|
||||
bar.createSelectionButtons(this);
|
||||
}
|
||||
content_in.add(ui_.getDataPanel(), BorderLayout.CENTER);
|
||||
}
|
||||
public DataSetControlForm getUi() {
|
||||
return ui_;
|
||||
}
|
||||
public void setFilterUI(FilterWindow ui_in) {
|
||||
f_ui = ui_in;
|
||||
}
|
||||
public void ShowUI() {
|
||||
if (ui_ != null) {
|
||||
ui_.Show();
|
||||
if (f_ui != null)
|
||||
f_ui.ShowMatchesCount(getRowCountUI());
|
||||
}
|
||||
}
|
||||
public void ShowUI(Object key) {
|
||||
if (ui_ != null) {
|
||||
ui_.Show(key);
|
||||
if (f_ui != null)
|
||||
f_ui.ShowMatchesCount(getRowCountUI());
|
||||
}
|
||||
}
|
||||
public void ClearUI() {
|
||||
if ((ui_ != null) && ui_.isShown()) {
|
||||
ui_.ClearSelection();
|
||||
ui_.Clear();
|
||||
if (f_ui != null)
|
||||
f_ui.ShowNoMatches();
|
||||
}
|
||||
}
|
||||
public void RefreshUI() {
|
||||
if (ui_ != null) ui_.Refresh();
|
||||
}
|
||||
public int getRowCountUI() {
|
||||
return ui_.getRowCount();
|
||||
}
|
||||
public void SetCurrentObjectUI(Object pk) {
|
||||
if (ui_ != null) {
|
||||
//todo возможно проверить, что текущий объект уже соответствует ключу, и если да, то ничего делать.
|
||||
ui_.ClearSelection(); //сброс текущего объекта и всего что с ним связано.
|
||||
ui_.Select(pk);
|
||||
}
|
||||
}
|
||||
//столбы/ потом переименовать обратно в getUIColumnNames.сейчас так для скорости переноса.
|
||||
public String[] getUIColumnNames() {
|
||||
return new String[]{};
|
||||
}
|
||||
protected DataSetControlForm createUI() {
|
||||
return null;
|
||||
}
|
||||
public boolean hasUI() {
|
||||
return ui_ != null;
|
||||
}
|
||||
public void CheckAll(boolean flag) {
|
||||
for (D object : Data.values()) {
|
||||
if (object.isVisible())
|
||||
object.Select(flag);
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
public D getFirstRecord() {
|
||||
return Data.values().stream().findFirst().orElse(null);
|
||||
}
|
||||
public Vector<D> getOrderedRecords(Comparator<D> comparator) {
|
||||
Vector<D> res = new Vector<>(Data.values());
|
||||
res.sort(comparator);
|
||||
return res;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public DBObjectDialog<D, ? extends DialogFields> getDialog() {
|
||||
return null;
|
||||
}
|
||||
public boolean ShowAddObjectDialog(DBObject object) {
|
||||
return getDialog().ShowDialog(getSingleDescription() + ": добавление", object);
|
||||
}
|
||||
public boolean ShowEditObjectDialog(DBObject object) {
|
||||
DBObjectDialog dialog = getDialog();
|
||||
dialog.edit = true;
|
||||
dialog.SetEditLimits();
|
||||
return dialog.ShowDialog(getSingleDescription() + ": редактирование", object);
|
||||
}
|
||||
public boolean ViewObject(DBObject object) {
|
||||
DBObjectDialog dialog = getDialog();
|
||||
dialog.SetReadonly();
|
||||
dialog.ShowDialog(getSingleDescription() + ": просмотр", object);
|
||||
return false;
|
||||
}
|
||||
public boolean ShowDeleteObjectDialog(DBObject object) {
|
||||
return UI.Warning(getSingleDescription() + " " + object.getBDialogName() + " будет удален(а)");
|
||||
}
|
||||
public String QName() {
|
||||
return "\"" + Name + "\"";
|
||||
}
|
||||
public String getPKName() {
|
||||
return "";
|
||||
} //получить имя ключевого поля. нужно для таблиц.
|
||||
public String getPluralDescription() {
|
||||
return "";
|
||||
}
|
||||
public String getSingleDescription() {
|
||||
return "";
|
||||
}
|
||||
//времянки
|
||||
public Current CurrentName() {
|
||||
return Current.Undefined;
|
||||
}
|
||||
public boolean CheckCurrent(TextLog log) {
|
||||
return Current.Check(log, CurrentName());
|
||||
}
|
||||
public boolean hasCurrent() {
|
||||
return Current.get(CurrentName()) != null;
|
||||
}
|
||||
public void dropCurrent() {
|
||||
Current.set(CurrentName(), null);
|
||||
}
|
||||
public D getCurrent() {
|
||||
return (D) Current.get(CurrentName());
|
||||
}
|
||||
public void setCurrent(D o) {
|
||||
Current.set(CurrentName(), o);
|
||||
}
|
||||
//-
|
||||
public void put(Object key, D object) {
|
||||
Data.put((K) key, object);
|
||||
}
|
||||
public D get(Object key) {
|
||||
return Data.get(key);
|
||||
}
|
||||
public Object getFieldAt(D object, int columnIndex) {
|
||||
return null;
|
||||
}
|
||||
public void clear() {
|
||||
Data.clear();
|
||||
}
|
||||
public int size() {
|
||||
return Data.size();
|
||||
}
|
||||
public boolean containsKey(Object key) {
|
||||
return Data.containsKey(key);
|
||||
}
|
||||
//-
|
||||
public Vector<K> getVisibleKeys() {
|
||||
Comparator<D> comparator = getComparator();
|
||||
Vector<K> res = new Vector<>();
|
||||
if (comparator == null) {
|
||||
for (K key : Data.keySet())
|
||||
if (Data.get(key).isVisible())
|
||||
res.add(key);
|
||||
} else {
|
||||
Vector<D> raw = new Vector<>();
|
||||
for (D object : Data.values()) {
|
||||
if (object.isVisible())
|
||||
raw.add(object);
|
||||
}
|
||||
raw.sort(comparator);
|
||||
for (D object : raw)
|
||||
res.add((K) object.getPK());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
protected Comparator<D> getComparator() {
|
||||
return null;
|
||||
}
|
||||
public int getCheckedCount() {
|
||||
return (int) Data.values().stream().filter(d -> d.isVisible() && d.isSelected()).count();
|
||||
}
|
||||
public Vector<D> getCheckedItems() {
|
||||
return Data.values().stream().filter(d -> d.isVisible() && d.isSelected()).collect(Collectors.toCollection(Vector::new));
|
||||
}
|
||||
public Vector<K> getCheckedKeys() {
|
||||
return Data.values().stream().filter(DBObject::isSelected).map(d -> (K) d.getPK()).collect(Collectors.toCollection(Vector::new));
|
||||
}
|
||||
//--
|
||||
public void SaveLastSelections() {
|
||||
if (hasUI()) {
|
||||
Object lastPk = null;
|
||||
if ((CurrentName() != Current.Undefined) && (getCurrent() != null))
|
||||
lastPk = getCurrent().getPK();
|
||||
if (!selections.containsKey(getClass()))
|
||||
selections.put(getClass(), lastPk);
|
||||
else selections.replace(getClass(), lastPk);
|
||||
}
|
||||
}
|
||||
public void RestoreLastSelections() {
|
||||
if (hasUI()) {
|
||||
Object lastPk = selections.get(getClass());
|
||||
// if (lastPk != null) UI.Info(this.getClass() + ":" + lastPk.toString());
|
||||
if ((CurrentName() != Current.Undefined) && (lastPk != null)) {
|
||||
// UI.Info(lastPk.toString());
|
||||
// System.out.println(ui);
|
||||
// UI.Info("+");
|
||||
ui_.Select(lastPk);
|
||||
}
|
||||
}
|
||||
}
|
||||
//---
|
||||
// применить значение фильтра к фильру объекта напирмер Message.filterValue = text;
|
||||
public void changeColumnFilterValue(int columnIndex, String text) {
|
||||
}
|
||||
public Object getColumnFilterValue(int columnIndex) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
11
src/Common/Database/DataSetAnchestor.java
Normal file
11
src/Common/Database/DataSetAnchestor.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package Common.Database;
|
||||
import java.util.LinkedHashMap;
|
||||
public abstract class DataSetAnchestor {
|
||||
//чтобы обмануть стирание типов во всех параметризованных полях. используется не во всех потомках.
|
||||
//ибо не все наборы данных относятся к базам.
|
||||
public LinkedHashMap<String, DBTableColumn> columns = new LinkedHashMap<>();
|
||||
//то же самое. на самом деле внешние ключи бывают только у таблиц бд
|
||||
public LinkedHashMap<Class<? extends DBObject>, FKBehaviour> getFKDependencies() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
274
src/Common/Database/Database.java
Normal file
274
src/Common/Database/Database.java
Normal file
@@ -0,0 +1,274 @@
|
||||
package Common.Database;
|
||||
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 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, Utils.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();
|
||||
}
|
||||
}
|
||||
9
src/Common/Database/FKBehaviour.java
Normal file
9
src/Common/Database/FKBehaviour.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package Common.Database;
|
||||
public class FKBehaviour {
|
||||
public FKDataBehaviour data; //поведение данных внешнего ключа при удалении/модификации
|
||||
public FKCurrentObjectBehaviuor ui; //поведение интерфейсов таблиц внешнего ключа при показе текущего объекта.
|
||||
public FKBehaviour(FKDataBehaviour data_in, FKCurrentObjectBehaviuor ui_in) {
|
||||
data = data_in;
|
||||
ui = ui_in;
|
||||
}
|
||||
}
|
||||
5
src/Common/Database/FKCurrentObjectBehaviuor.java
Normal file
5
src/Common/Database/FKCurrentObjectBehaviuor.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package Common.Database;
|
||||
public enum FKCurrentObjectBehaviuor {
|
||||
PASSIVE,
|
||||
ACTIVE
|
||||
}
|
||||
7
src/Common/Database/FKDataBehaviour.java
Normal file
7
src/Common/Database/FKDataBehaviour.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package Common.Database;
|
||||
//поведение таблиц имеющих внешние ключи
|
||||
public enum FKDataBehaviour {
|
||||
NONE,
|
||||
DROP,
|
||||
DELETE
|
||||
}
|
||||
261
src/Common/Database/SQLITE/SQLiteDatabase.java
Normal file
261
src/Common/Database/SQLITE/SQLiteDatabase.java
Normal file
@@ -0,0 +1,261 @@
|
||||
package Common.Database.SQLITE;
|
||||
import Common.Database.DBObject;
|
||||
import Common.Database.DBTable;
|
||||
import Common.Database.DBTableColumn;
|
||||
import Common.Database.Database;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
import Visual_DVM_2021.Passes.PassException;
|
||||
import javafx.util.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Vector;
|
||||
|
||||
import static Common.Utils.Utils.requireNonNullElse;
|
||||
public abstract class SQLiteDatabase extends Database {
|
||||
protected Connection conn = null;
|
||||
protected Statement statement = null;
|
||||
protected ResultSet resSet = null;
|
||||
public LinkedHashMap<Class<? extends DBObject>, PreparedStatement> insertStatements = new LinkedHashMap<>();
|
||||
public LinkedHashMap<Class<? extends DBObject>, PreparedStatement> updateStatements = new LinkedHashMap<>();
|
||||
public LinkedHashMap<Class<? extends DBObject>, PreparedStatement> deleteStatements = new LinkedHashMap<>();
|
||||
//->>
|
||||
public SQLiteDatabase(File file_in) {
|
||||
super(file_in);
|
||||
}
|
||||
@Override
|
||||
protected void connect() throws Exception {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
try {
|
||||
conn = DriverManager.getConnection("jdbc:sqlite:" + file.getAbsolutePath());
|
||||
break;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
conn = null;
|
||||
System.gc();
|
||||
Utils.sleep(2000);
|
||||
}
|
||||
}
|
||||
if (conn == null)
|
||||
throw new PassException("Внутренняя ошибка sqlite. Не удалось установить соединение за 5 попыток.");
|
||||
statement = conn.createStatement();
|
||||
}
|
||||
@Override
|
||||
protected void disconnect() throws Exception {
|
||||
if (conn != null) {
|
||||
conn.close();
|
||||
conn = null;
|
||||
}
|
||||
if (statement != null) {
|
||||
statement.close();
|
||||
statement = null;
|
||||
}
|
||||
if (resSet != null) {
|
||||
resSet.close();
|
||||
resSet = null;
|
||||
}
|
||||
for (PreparedStatement preparedStatement : insertStatements.values()) {
|
||||
if (preparedStatement != null)
|
||||
preparedStatement.close();
|
||||
}
|
||||
for (PreparedStatement preparedStatement : updateStatements.values()) {
|
||||
if (preparedStatement != null)
|
||||
preparedStatement.close();
|
||||
}
|
||||
for (PreparedStatement preparedStatement : deleteStatements.values()) {
|
||||
if (preparedStatement != null)
|
||||
preparedStatement.close();
|
||||
}
|
||||
insertStatements.clear();
|
||||
updateStatements.clear();
|
||||
deleteStatements.clear();
|
||||
//-->>
|
||||
System.gc();
|
||||
//->>
|
||||
}
|
||||
@Override
|
||||
protected void beginTransaction() throws Exception {
|
||||
conn.setAutoCommit(false);
|
||||
}
|
||||
@Override
|
||||
protected void commit() throws Exception {
|
||||
conn.commit();
|
||||
conn.setAutoCommit(true);
|
||||
}
|
||||
@Override
|
||||
protected boolean TableExists(DBTable table) throws Exception {
|
||||
int count = 0;
|
||||
resSet = statement.executeQuery("SELECT count(*) FROM 'sqlite_master' WHERE type=\"table\" AND name=" + table.QName());
|
||||
if (resSet.next())
|
||||
count = resSet.getInt(1);
|
||||
return count > 0;
|
||||
}
|
||||
@Override
|
||||
public void CreateTable(DBTable table) throws Exception {
|
||||
if (table.columns.size() > 0) {
|
||||
if (TableExists(table)) {
|
||||
Vector<String> existing_columns = new Vector<>();
|
||||
Vector<String> columns_to_create = new Vector<>();
|
||||
//предполагаем что первичный ключ и атрибуты не изменятся.
|
||||
//и что не будет столбов с одинаковыми именами но разными типами.
|
||||
resSet = statement.executeQuery("pragma table_info(" + table.QName() + ")");
|
||||
while (resSet.next())
|
||||
existing_columns.add(resSet.getString(2));
|
||||
//-
|
||||
for (String target_column : table.columns.keySet()) {
|
||||
if (!existing_columns.contains(target_column))
|
||||
columns_to_create.add(target_column);
|
||||
}
|
||||
for (String cn : columns_to_create)
|
||||
statement.execute("ALTER TABLE " + table.QName() + " ADD COLUMN " + table.columns.get(cn));
|
||||
} else {
|
||||
String cmd = "CREATE TABLE if not exists " + table.QName() + " ";
|
||||
Vector<String> columns_names = new Vector<>();
|
||||
for (DBTableColumn column : table.columns.values())
|
||||
columns_names.add(column.toString());
|
||||
cmd += Utils.RBrackets(String.join(",", columns_names));
|
||||
statement.execute(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void prepareTablesStatements() throws Exception {
|
||||
for (DBTable table : tables.values()) {
|
||||
//---
|
||||
Vector<String> column_names = new Vector<>();
|
||||
Vector<String> column_values = new Vector<>();
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (!column.AutoIncrement) {
|
||||
column_names.add(column.QName());
|
||||
column_values.add("?");
|
||||
}
|
||||
}
|
||||
insertStatements.put(table.d, conn.prepareStatement(
|
||||
"INSERT OR REPLACE INTO " + table.QName() + " " +
|
||||
Utils.RBrackets(String.join(",", column_names)) + " " + "VALUES " +
|
||||
Utils.RBrackets(String.join(",", column_values))));
|
||||
//------------------------------------------------------------------------------->>
|
||||
Vector<String> new_values = new Vector();
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (!column.AutoIncrement) {
|
||||
new_values.add(column.QName() + "=?");
|
||||
}
|
||||
}
|
||||
updateStatements.put(table.d, conn.prepareStatement(
|
||||
"UPDATE " + table.QName() + " " +
|
||||
"SET " + String.join(",", new_values) + " " +
|
||||
"WHERE (" + table.PK.QName() + "=?)"
|
||||
));
|
||||
//---------------------------------------------------------------------------------->>>
|
||||
deleteStatements.put(table.d, conn.prepareStatement("DELETE FROM " + table.QName() + " WHERE " + table.PK.QName() + " = ?"));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void delete(DBTable table, DBObject o) throws Exception {
|
||||
PreparedStatement ps = deleteStatements.get(table.d);
|
||||
ps.setObject(1, o.getPK());
|
||||
ps.executeUpdate();
|
||||
}
|
||||
protected <K, D extends DBObject> Pair<K, D> readRecord(DBTable<K, D> table) throws Exception {
|
||||
D o = table.d.newInstance();
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
Object field_value = null;
|
||||
switch (column.type) {
|
||||
case DOUBLE:
|
||||
field_value = requireNonNullElse(resSet.getDouble(column.Name), 0);
|
||||
break;
|
||||
case UNDEFINED:
|
||||
break;
|
||||
case INT:
|
||||
field_value = requireNonNullElse(resSet.getInt(column.Name), 0);
|
||||
break;
|
||||
case LONG:
|
||||
field_value = requireNonNullElse(resSet.getLong(column.Name), 0);
|
||||
break;
|
||||
case STRING:
|
||||
if (table.d.getField(column.Name).getType().isEnum()) {
|
||||
Class enum_class = Class.forName(table.d.getField(column.Name).getType().getName());
|
||||
String string = resSet.getString(column.Name);
|
||||
Object[] enum_constants = enum_class.getEnumConstants();
|
||||
if (string != null) {
|
||||
try {
|
||||
field_value = Enum.valueOf(enum_class, string);
|
||||
} catch (Exception ignore) {
|
||||
System.out.println(Utils.Brackets(string) + "not found");
|
||||
field_value = enum_constants[0];
|
||||
System.out.println(field_value);
|
||||
}
|
||||
} else field_value = enum_constants[0];
|
||||
} else
|
||||
field_value = requireNonNullElse(resSet.getString(column.Name), "");
|
||||
break;
|
||||
}
|
||||
if (field_value != null) {
|
||||
table.d.getField(column.Name).set(o, field_value);
|
||||
} else
|
||||
throw new PassException("Ошибка при загрузке поля " + Utils.Brackets(column.Name) + " класса " + Utils.Brackets(table.d.getSimpleName()));
|
||||
}
|
||||
return new Pair<>((K) o.getPK(), o);
|
||||
}
|
||||
@Override
|
||||
protected <K, D extends DBObject> void loadAll(DBTable<K, D> table) throws Exception {
|
||||
resSet = statement.executeQuery("SELECT * FROM " + table.QName());
|
||||
while (resSet.next()) {
|
||||
Pair<K, D> record = readRecord(table);
|
||||
table.Data.put(record.getKey(), record.getValue());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void insert(DBTable table, DBObject o) throws Exception {
|
||||
PreparedStatement ps = insertStatements.get(table.d);
|
||||
if (ps == null)
|
||||
UI.Info("INSERT NULL");
|
||||
int i = 1;
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (!column.AutoIncrement) {
|
||||
ps.setObject(i, o.getClass().getField(column.Name).get(o));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ps.execute();
|
||||
//-->
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (column.AutoIncrement) {
|
||||
resSet = statement.executeQuery("SELECT MAX(" + column.QName() + ") AS LAST FROM " + table.QName());
|
||||
String maxId = resSet.getString("LAST");
|
||||
int intMaxId = Integer.parseInt(maxId);
|
||||
o.getClass().getField(column.Name).set(o, intMaxId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void update(DBTable table, DBObject o) throws Exception {
|
||||
PreparedStatement ps = updateStatements.get(table.d);
|
||||
if (ps == null)
|
||||
UI.Info("UPDATE NULL");
|
||||
int i = 1;
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (!column.AutoIncrement) {
|
||||
ps.setObject(i, o.getClass().getField(column.Name).get(o));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ps.setObject(i, o.getPK());
|
||||
ps.executeUpdate();
|
||||
}
|
||||
@Override
|
||||
protected void deleteAll(DBTable table) throws Exception {
|
||||
statement.executeUpdate("DELETE FROM " + table.QName());
|
||||
}
|
||||
@Override
|
||||
protected void resetAI(DBTable table) throws Exception {
|
||||
statement.executeUpdate("UPDATE SQLITE_SEQUENCE SET SEQ = 0 WHERE NAME =" + table.QName());
|
||||
}
|
||||
//--
|
||||
//https://stackoverflow.com/questions/8558099/sqlite-query-with-byte-where-clause
|
||||
|
||||
}
|
||||
43
src/Common/Database/TableFilter.java
Normal file
43
src/Common/Database/TableFilter.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package Common.Database;
|
||||
import Common.UI.Menus_2023.StableMenuItem;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
public class TableFilter<D extends DBObject> {
|
||||
DataSet table;
|
||||
public JMenuItem menuItem; //пункт меню фильтра. ( возможно потом сделать и кнопку)
|
||||
String description;
|
||||
boolean active = false; //включен ли фильтр
|
||||
public int count = 0;
|
||||
protected boolean validate(D object) {
|
||||
return true;
|
||||
}
|
||||
public boolean Validate(D object) {
|
||||
boolean valid;
|
||||
if (valid=validate(object))
|
||||
count++;
|
||||
return !active || valid;
|
||||
}
|
||||
static String getNotActiveIconPath() {
|
||||
return "/icons/NotPick.png";
|
||||
}
|
||||
static String getActiveIconPath() {
|
||||
return "/icons/Pick.png";
|
||||
}
|
||||
public TableFilter(DataSet table_in, String description_in) {
|
||||
table = table_in;
|
||||
menuItem = new StableMenuItem((description = description_in)+" (0)");
|
||||
menuItem.addActionListener(e -> {
|
||||
active = !active;
|
||||
Mark();
|
||||
table.ShowUI();
|
||||
});
|
||||
Mark();
|
||||
}
|
||||
public void Mark() {
|
||||
menuItem.setIcon(Utils.getIcon(active ? getActiveIconPath() : getNotActiveIconPath()));
|
||||
}
|
||||
public void ShowDescriptionAndCount() {
|
||||
menuItem.setText(description + " " + Utils.RBrackets(count));
|
||||
}
|
||||
}
|
||||
30
src/Common/Database/iDBObject.java
Normal file
30
src/Common/Database/iDBObject.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package Common.Database;
|
||||
import Common.Utils.Utils;
|
||||
import com.sun.org.glassfish.gmbal.Description;
|
||||
//автоинкрементальный ключ
|
||||
public class iDBObject extends DBObject {
|
||||
@Description("PRIMARY KEY,AUTOINCREMENT")
|
||||
public int id;
|
||||
@Override
|
||||
public Object getPK() {
|
||||
return id;
|
||||
}
|
||||
@Override
|
||||
public String getFKName() {
|
||||
return getClass().getSimpleName().toLowerCase() + "_id";
|
||||
}
|
||||
@Override
|
||||
public Object getEmptyFK() {
|
||||
return Utils.Nan;
|
||||
}
|
||||
//---
|
||||
@Override
|
||||
public void SynchronizeFields(DBObject src) {
|
||||
super.SynchronizeFields(src);
|
||||
id = ((iDBObject)src).id;
|
||||
}
|
||||
public iDBObject(){}
|
||||
public iDBObject(iDBObject src){
|
||||
this.SynchronizeFields(src);
|
||||
}
|
||||
}
|
||||
6
src/Common/Database/iDBTable.java
Normal file
6
src/Common/Database/iDBTable.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package Common.Database;
|
||||
public abstract class iDBTable<D extends iDBObject> extends DBTable<Integer, D> {
|
||||
public iDBTable(Class<D> d_in) {
|
||||
super(Integer.class, d_in);
|
||||
}
|
||||
}
|
||||
35
src/Common/Database/nDBObject.java
Normal file
35
src/Common/Database/nDBObject.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package Common.Database;
|
||||
import Common.Utils.Utils;
|
||||
import com.sun.org.glassfish.gmbal.Description;
|
||||
public abstract class nDBObject extends DBObject {
|
||||
String getClassNameL() {
|
||||
return getClass().getSimpleName().toLowerCase();
|
||||
}
|
||||
@Description("PRIMARY KEY, UNIQUE")
|
||||
public String id = "";
|
||||
@Override
|
||||
public Object getPK() {
|
||||
return id;
|
||||
}
|
||||
@Override
|
||||
public String getFKName() {
|
||||
return getClassNameL() + "_id";
|
||||
}
|
||||
@Override
|
||||
public Object getEmptyFK() {
|
||||
return "";
|
||||
}
|
||||
public void genName() {
|
||||
id = Utils.getDateName(getClassNameL());
|
||||
}
|
||||
//-
|
||||
@Override
|
||||
public void SynchronizeFields(DBObject src) {
|
||||
super.SynchronizeFields(src);
|
||||
id = ((nDBObject)src).id;
|
||||
}
|
||||
public nDBObject(nDBObject src){
|
||||
this.SynchronizeFields(src);
|
||||
}
|
||||
public nDBObject(){}
|
||||
}
|
||||
32
src/Common/Database/rDBObject.java
Normal file
32
src/Common/Database/rDBObject.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package Common.Database;
|
||||
import java.util.Date;
|
||||
//объект репозитория. ключ имя, и есть данные отправителя.
|
||||
public class rDBObject extends nDBObject {
|
||||
public String sender_name = "";
|
||||
public String sender_address = "";
|
||||
public String description = "";
|
||||
//-
|
||||
public long date = 0;
|
||||
public long change_date;
|
||||
public Date getDate() {
|
||||
return new Date(date);
|
||||
}
|
||||
public Date getChangeDate() {
|
||||
return new Date(change_date);
|
||||
}
|
||||
@Override
|
||||
public void SynchronizeFields(DBObject src) {
|
||||
super.SynchronizeFields(src);
|
||||
rDBObject r = (rDBObject) src;
|
||||
sender_name = r.sender_name;
|
||||
sender_address = r.sender_address;
|
||||
description = r.description;
|
||||
date = r.date;
|
||||
change_date = r.change_date;
|
||||
}
|
||||
public rDBObject(rDBObject src) {
|
||||
this.SynchronizeFields(src);
|
||||
}
|
||||
public rDBObject() {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user