powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Объединение sql запросов в один класс - упрощение (Обновлено)
25 сообщений из 79, страница 1 из 4
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632103
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не кидать тапками.

Я создавал тему подобную уже. Но не хочется писать там ибо много сообщений.

Я постараюсь описать все от а до я что бы не было кучи лишних вопросов и прочего, одним словом срача.

Итак. Я не использую никакие фреймворки, ОРМ и прочее - все пишется ручками (используются либы). Почему так? Поясняю - Проект начинал писаться без этого всего и сейчас, когда он уже почти готов и в нем просто дофига функционала, переписывать никто не будет ибо а) нет на это времени и б) нет средств. По сему, пожалуйста, не надо про это писать. Я знаю как сейчас делается, но причину по которой переделываться не будет я озвучил.


Есть класс DataSource (Синглтон). Предоставляется библиотекой Commons dbcp2. Служит для пула подключений (при старте приложения создаётся 10 подключений к бд и хранятся в BasicDataSource).


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
public class DataSource {

	private static final DataSource INSTANCE = new DataSource();

	private final BasicDataSource basicDataSource = new BasicDataSource();

	private DataSource() {

		try {

            basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");

            basicDataSource.setUrl("jdbc:mysql://localhost:3306/db");

            basicDataSource.setUsername("root");

            basicDataSource.setPassword("root");

            basicDataSource.setInitialSize(10);

            basicDataSource.setMaxWaitMillis(180000);

            basicDataSource.setDefaultAutoCommit(true);

            basicDataSource.setPoolPreparedStatements(true);

            basicDataSource.setConnectionProperties("useUnicode=true;characterEncoding=utf8");

            QueryRunner queryRunner = new QueryRunner(basicDataSource);

			queryRunner.update("SET GLOBAL sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';");
			queryRunner.update("SET SESSION sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';");

		} catch (Exception e) {
			
		}

	}

	public static DataSource getInstance() {
		return INSTANCE;
	}

	public BasicDataSource getDataSource() {
		return basicDataSource;
	}

	public static JSONObject getDbResultObject(ResultSet rs) throws SQLException {
		JSONObject result = new JSONObject();
		int index = 0;
		while(rs.next()) {
			result.put(index, getDbRow(rs));
			index++;
		}
		return result;
	}

	public static JSONArray getDbResultArray(ResultSet rs) throws SQLException {
		JSONArray result = new JSONArray();
		while(rs.next()) {
			result.add(getDbRow(rs));
		}
		return result;
	}

	public static JSONObject getDbSingleRow(ResultSet rs) throws SQLException {
		return rs.next()? getDbRow(rs): new JSONObject();
	}

	private static JSONObject getDbRow(ResultSet rs) throws SQLException {
		JSONObject result = new JSONObject();
		ResultSetMetaData meta = rs.getMetaData();
		for(int i=0;i<meta.getColumnCount();i++) {
			Object obj = rs.getObject(i+1);
			if(obj instanceof Time) {
				String date = TIME_FORMAT.format((java.util.Date) obj);
				result.put(meta.getColumnLabel(i+1), date);
			} else if(obj instanceof Timestamp) {
				String date = DATE_TIME_FORMAT.format((java.util.Date) obj);
				result.put(meta.getColumnLabel(i+1), date);
			} else if(obj instanceof java.util.Date) {
				String date = DATE_FORMAT.format((java.util.Date) obj);
				result.put(meta.getColumnLabel(i+1), date);
			} else {
				result.put(meta.getColumnLabel(i+1), rs.getObject(i+1)==null?"":obj);
			}
		}
		return result;
	}

}




Далее.

Есть классы в которых прописаны запросы к бд. Это не синглтоны.
Их всего 3:
DataBaseUser(Запрос которые отвечают за пользователя),
DataBaseAdmin(Запросы которые относятся к внутреннему функционалу проекта),
DataBaseChat (Запросы которые относятся к чату)

Я специально разделил эти запросы: Все запросы относятся только к той области где они применяются. К примеру DataBaseChat обслуживает чат.

Код DataBaseAdmin:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
public class DataBaseAdmin {

    private QueryRunner queryRunner;
    
    public DataBaseUser(BasicDataSource basicDataSource) {
        this.queryRunner = new QueryRunner(basicDataSource);
    }

    // Примеры запросов
    public JSONArray userGetPayments(int userId, boolean paid, boolean active, boolean wait, boolean finish, boolean activate) throws SQLException {
        return getQueryRunner().query("SELECT p.*, s.id AS site_id, url FROM payments AS p LEFT JOIN site AS s ON s.id=p.site_id WHERE p.user_id = ? AND p.paid = ? AND active = ? AND wait = ? AND finish = ? AND (activate = ?  OR activate = ?);", new ResultSetHandler<JSONArray>() {
            public JSONArray handle(ResultSet rs) throws SQLException {
                return DataSource.getDbResultArray(rs);
            }
        }, userId, paid, active, wait, finish, activate, !activate);
    }

    public JSONObject userGetInfo(int userId) throws SQLException {
        return getQueryRunner().query(SqlCore.SQL_USER_INFO_GET, new ResultSetHandler<JSONObject>() {
            public JSONObject handle(ResultSet rs) throws SQLException {
                return DataSource.getDbSingleRow(rs);
            }
        }, userId);
    }

    public int paymentAdd(Payment pm) throws SQLException {
        return getQueryRunner().insert(SqlCore.SQL_PAYMENT_ADD, new ScalarHandler<Long>(), pm.getUserId(), pm.getSiteId(), pm.getRateId(), pm.getStart(), pm.getEnd(), pm.isPaid(), pm.isActive(), pm.isWait(), pm.isFinish(), pm.isActivate()).intValue();
    }

    public boolean paymentUpdate(Payment pm) throws SQLException {
        return getQueryRunner().update(SqlCore.SQL_PAYMENT_UPDATE, pm.getUserId(), pm.getSiteId(), pm.getRateId(), pm.getStart(), pm.getEnd(), pm.isPaid(), pm.isActive(), pm.isWait(), pm.isFinish(), pm.isActivate(), pm.isError(), pm.getMessage(), pm.getId())>0;
    }

}



Остальные два класса похожи конструктором и полем - все остальное разное.

Тут прописаны все запросы. В каждой выборке могут быть своя обработка результата. Запросы бывают 3 типов: QUERY, INSERT, UPDATE.
Сами запросы я делаю при помощи библиотеки Commons DbUtils - QuerryRunner. Ему передаётся BasicDataSource из которого достаётся Connection.

Использование этих классов:

Код: java
1.
2.
3.
4.
BasicDataSource BDS = Core.getDataSource();

DataBaseUser dbUser = new DataBaseUser(BDS);
DataBaseAdmin dbAdmin = new DataBaseAdmin(BDS);



Где мне нужно обратиться к базе я создаю экземпляры классов у которых есть методы. Вызываю нужные методы. После окончания работы с бд я выполняю возврат подключения в пул:

Код: java
1.
BDS.getConnection().close();



Вот такая вот система. Знаю не очень удобно и красиво.
Теперь вопрос.

Как можно это все сжать или скомпоновать что бы имея один класс получать доступ ко всем методам классов. Приведу пример использования:

Код: java
1.
2.
3.
4.
5.
 DataBase db = new DataBase(getDataSource());

 db.getDbUser().getUserIdByHash(user.getHash())

 db.close();



Пример самого класса DataBase:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
public class DataBase {

    private DataBaseUser dbUser;
    private DataBaseAdmin dbAdmin;
    private DataBaseChat dbChat;

    private QueryRunner queryRunner;

    public DataBase(BasicDataSource basicDataSource) {

        queryRunner = new QueryRunner(basicDataSource);

        dbUser = new DataBaseUser(queryRunner);
        dbAdmin = new DataBaseAdmin(queryRunner);
        dbChat = new DataBaseChat(queryRunner);

    }

    public DataBaseUser getDbUser() {
        return dbUser;
    }

    public DataBaseAdmin getDbAdmin() {
        return dbAdmin;
    }

    public DataBaseChat getDbChat() {
        return dbChat;
    }

    public void close() throws SQLException {
        queryRunner.getDataSource().getConnection().close();
    }

}



Может есть более элегантный вариант?

Спасибо за внимание!
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632126
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tsyklop,
что ты делаешь с json, которые тебе возвращают твои запросы?
кто формирует запросы?
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632129
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вадяTsyklop,
что ты делаешь с json, которые тебе возвращают твои запросы?
кто формирует запросы?

JSON перегоняю в объект посредством Gson . Знаю может это не совсем ахти. но пока что так. Пытался сделать аля ОРМ.

Формирует их QuerryRunner - по сути он делает PrepareStatment, подставляет переданные параметры в знаки ? в строке запроса. Ну а ResultSetHandler служит для обработки результата запроса.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632139
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tsyklop,
конечная цель полученных данных?
отправка клиентк? объект это что?
зачем столько преобразований?

запрос на получении откудп приходит? от клиента?
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632171
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tsyklop,
Никакого смысла в объединении класса по работе с чатом с классом Users нету.
И ты так членораздельно и не объяснил зачем это нужно.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632202
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsyklopJSON перегоняю в объект посредством Gson я бы сразу делал из результсета объект (хотя надо знать что это за объект и для чего он нужен, может это шаг пропустить)
и почему не сделать так
три класса
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
 public class dbAdmin | dbUser | dbChat{


 public XObject (......){
      try (Connection con = dataSource.getConnection();
             Statement st = con.createStatement()){
            st.executeQuery("Select ....;");
           
         .... результсет в объект...

        } catch (SQLException | IOException ex) {
           ..................
        }
 return объект;
}

public YObject (..){...}



}


а в синглтоне dataSource...
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632207
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вадяTsyklop,
конечная цель полученных данных?
отправка клиентк? объект это что?
зачем столько преобразований?

запрос на получении откудп приходит? от клиента?

Не только. Смотря какой запрос приходит то и делается. Нужен объект для работы с ним вот и вытягиваю. Не обязательно он отдаётся клиенту
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632208
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вадя,
За меня это все делает QuerryRunner в каждом по сути запросе.
Можно как-то сделать с QuerryRunner, что бы как-то обобщить все.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632209
chpasha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123И ты так членораздельно и не объяснил зачем это нужно
а говорил, что живешь давно ;)
понятно зачем - хочется создавать один объект вместо трех, иметь один "супер" класс.

ТС - зачем создавать еще одну тему о том же самом? ты думаешь набегут другие, которые тебе что-то присоветуют? не набегут - тут только мы. А если бы набежали, то начали советовать все тоже самое, на 5ти страницах. Можно сделать только либо так, как ты уже написал, либо скинуть все обратно в один файл. Какой магии ты еще в этом месте ожидаешь?
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632212
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chpashaТС - зачем создавать еще одну тему о том же самом? ты думаешь набегут другие, которые тебе что-то присоветуют? не набегут - тут только мы. А если бы набежали, то начали советовать все тоже самое, на 5ти страницах. Можно сделать только либо так, как ты уже написал, либо скинуть все обратно в один файл. Какой магии ты еще в этом месте ожидаешь?

первый пост читали? я объяснил почему я создал новую тему.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632215
chpasha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tsyklopпервый пост читали? я объяснил почему я создал новую тему
я обычно читаю и даже иногда понимаю написанное. Объяснение - курам насмех, тема - исчерпана. Если собираешься продолжать в подобном ключе, будешь очень быстро послан нахер
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632219
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chpashaМожно сделать только либо так, как ты уже написал, либо скинуть все обратно в один файл
+1))
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
//либо 
контекстПодсистемы = new Подсистема_A();
контекстПодсистемы.Работаем()
...
контекстПодсистемы = new Подсистема_B();
контекстПодсистемы.Работаем()
//либо
контекст = new Подсистема А+B
контекст.Работаем()


chpashaпонятно зачем - хочется создавать один объект вместо трех, иметь один "супер" класс.
я бы понял, если бы он до этого не разделил всё на 3 класса))
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632220
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chpashaОбъяснение - курам насмех, тема - исчерпана. Если собираешься продолжать в подобном ключе, будешь очень быстро послан нахер
+1
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632223
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tsyklopпервый пост читали? я объяснил почему я создал новую тему.
Но понятнее, ведь, не стало. Конструкторы не нужны. Нужны синглтоны и Dependency Injection.

Смотрите вот ваш код:

Код: java
1.
2.
3.
4.
5.
DataBase db = new DataBase(getDataSource());

 db.getDbUser().getUserIdByHash(user.getHash())

 db.close()



Код нарушает SRP, потому что в нем инфраструктура смешана с бизнес-логикой.

Инфраструктура
Код: java
1.
2.
3.
DataBase db = new DataBase(getDataSource());
db.get...
db.close()


Её не должно быть в каждом методе где вы пытаетесь использова DbUser или другой аналогичный класс.
Бизнес-логика:
Код: java
1.
dbUser.getUserIdByHash(user.getHash());



Чтобы ваш код превратить в чистую бизнес-логику, нужно инфраструктуру вынести в общий код.
Например это можнo реализовать через Proxy. Или паттерн Template method. Лучше через Proxy чтобы было меньше шума.

С другой стороны прокси у вас нужен только чтобы закрывать Connection. Так как вместо создания DataBase на каждый пук имеет смысл перейти на скиглтоны и инъкцию их экземпляров.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632224
chpasha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123я бы понял, если бы он до этого не разделил всё на 3 класса
он их разделил ровно по одной причине - стало много методов :)
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632225
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsyklopЗа меня это все делает QuerryRunner в каждом по сути запросе.он делает не всё, непонятно, что...
оставляя тебе проблему с закрытием конекта.
у тебя куча классов/методов....
я предлагаю только оставить 3. в которых методы будут возвращать конечный нужный объект.
избавишься от медленного преобразования в json, и от преобразования json в объект.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632226
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsyklopГде мне нужно обратиться к базе я создаю экземпляры классов у которых есть методы. Вызываю нужные методы. После окончания работы с бд я выполняю возврат подключения в пул:

Код: java
1.
BDS.getConnection().close();



Вот это вообще жуть. В приложении, сложнее Hello world вероятность того, что потекут коннекшены близка к 100%. Connection - от autocloseable - сделай хотя бы через try with resources, или делай все обращения через helper, который принимает лямбду, в которую передается connection, а все манипуляции с connection выполнять в helper'е.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632227
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz,
а с чего вы взяли что это я использую везде? и с чего вы взяли что создаётся новое подключение? я как бы описал откуда берется подключение и т.д.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632229
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вадяон делает не всё, непонятно, что...
оставляя тебе проблему с закрытием конекта.
у тебя куча классов/методов....
я предлагаю только оставить 3. в которых методы будут возвращать конечный нужный объект.
избавишься от медленного преобразования в json, и от преобразования json в объект.

почему же не понятно. он делает по сути то же Вы и пишете а мне отдаёт ResultSet, а я прохожусь в цикле по каждому найденному элементу и записываю в коллекцию. все.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632230
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot Локшин Марк
Вот это вообще жуть. В приложении, сложнее Hello world вероятность того, что потекут коннекшены близка к 100%. Connection - от autocloseable - сделай хотя бы через try with resources, или делай все обращения через helper, который принимает лямбду, в которую передается connection, а все манипуляции с connection выполнять в helper'е.[/quot]

я написал что это возврат конекшена в пул, а не его закрытие.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632233
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
тема закрыта.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632234
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chpashaPetro123я бы понял, если бы он до этого не разделил всё на 3 класса
он их разделил ровно по одной причине - стало много методов :)
ну и я бы разделил если он не врёт, и это 3 разные подсистемы. По крупному.
Обратное объединение нелогично).
Не будет ни сущностей, ни классов, ни подсистем.
Если только так:
Код: java
1.
база.Подсистема.МетодПодсистемы()


но выгода сомнительна.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632241
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tsyklop,
а с чего вы взяли что это я использую везде?

Ну, это вы такой код привели - не я.

Tsyklopи с чего вы взяли что создаётся новое подключение?
Буквоед? С точки зрения кода запуска запроса всё равно создаётся новое физическое подключение или создаётся новый Connection proxy со старым подключением. Если нужно вызывать Connection.close(), который где-то этот самый Connection создался.

Tsyklop я как бы описал откуда берется подключение и т.д.
Всё что вы пишете я прочитал и прокомментировал. Но вам плевать. Вы просто игнорируете то чего не понимаете и продолжаете писать одно и тоже разными словами из поста в пост.

Вы нигде ниразу не объяснили в чем именно проблема. Единственное ваше объяснение - хочу объединить 3 в 1 чтобы было как шампунька. На мои два вопроса "зачем" - вы ниразу не удосужились ответить.

Замечательно что вы немного упростили код, но, похоже, это потолок. Нужно дальше учиться.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632245
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tsyklopя написал что это возврат конекшена в пул, а не его закрытие.
С точки зрения кода, который его использует разницы нет. Но, вы как девочка готовы спорить о любой ерунде, которую вам пишут вместо того чтобы сконцентрироваться на проблеме и способах её решения.
...
Рейтинг: 0 / 0
Объединение sql запросов в один класс - упрощение (Обновлено)
    #39632255
Tsyklop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczС точки зрения кода, который его использует разницы нет. Но, вы как девочка готовы спорить о любой ерунде, которую вам пишут вместо того чтобы сконцентрироваться на проблеме и способах её решения.

я ни с кем не спорю. я слушаю всех и говорю как работает у меня.

Не создается новое подключение, а берется из пула подключений.
...
Рейтинг: 0 / 0
25 сообщений из 79, страница 1 из 4
Форумы / Java [игнор отключен] [закрыт для гостей] / Объединение sql запросов в один класс - упрощение (Обновлено)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]