Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Коннекты к базам, нужен совет 
V
    Опции темы
Bulat
Дата 6.7.2006, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 4
Всего: 57



Вообщем работаю с несколькими базами, где разные данные соответственно. Все коннекты держу в одном классе. Соответственно если нужны вызываю сам класс и методы. По коду программы приходиться коннектиться к нескольким базам одновременно, причем есть коды в таком виде что сначала получаю данные из одной базы, и в зависимости от того, что получил коннектюсь либо ко второй, либо к третьей и т.п. и все в одном методе класса. Тока допустим если у меня нет соединения с одной из баз программа сразу же выкидывает исключительную ситуацию, но возможно мне это база в данный момент не нужна, а сдругой работать не получается. Вот как бы это грамотно организовать, чтоб если даже один сервак(база) ляжет, без ущерба можно было работать с другими? 


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
mulya
Дата 6.7.2006, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 3.5.2006

Репутация: нет
Всего: нет



Я может вопроса не понял, а может ты его так путанно задал... короче я не вижу тут сложности, ну отвалилась база и чего? просто лови эксепшн и обрабатывай его правильно или вообще не обрабатывай, а работай себе дальше с тем что есть. 
PM MAIL   Вверх
Bulat
Дата 6.7.2006, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 4
Всего: 57



mulya, можно конечно для каждого отдельно отлавливать эксепшн, но это сколько раз код дублировать придется? smile 
А не обрабатывать, нет уж надо контролировать. 

Кроме того я заранее не знаю какая база мне понадобится => в метод нужно передовать все коннекты, а если сервак лег, то Connection con, вот этот самый con как null не передаст, а будет ругатся и я не смогу работать с остальными базами. 

Это сообщение отредактировал(а) Bulat - 6.7.2006, 12:24


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
carper
Дата 6.7.2006, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 1
Всего: 8



Bulat
Ничего не понял, ну есть коннекты, обращаться за ними надо не напрямую, а через, например, get метод, который может проверить жив ли еще/имеется коннект, при необходимости попытаться его, например, восстановить и вернуть на выбор: готовый коннект/код ошибки/сгенерированное исключение. 

И в загадочный метод передаем не все коннекты (на фиига они все вообще сдались), а пусть наш метод вызовет нужный ему коннект через соотв. фактори метод класса, ответственного за пул коннектов. 
PM MAIL   Вверх
Bulat
Дата 6.7.2006, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 4
Всего: 57



Цитата(carper @  6.7.2006,  12:40 Найти цитируемый пост)
Ничего не понял, ну есть коннекты, обращаться за ними надо не напрямую, а через, например, get метод, который может проверить жив ли еще/имеется коннект, при необходимости попытаться его, например, восстановить и вернуть на выбор: готовый коннект/код ошибки/сгенерированное исключение. 

Это у меня есть как раз в отдельном классе.

Цитата(carper @  6.7.2006,  12:40 Найти цитируемый пост)
И в загадочный метод передаем не все коннекты (на фиига они все вообще сдались), а пусть наш метод вызовет нужный ему коннект через соотв. фактори метод класса, ответственного за пул коннектов. 

Даже если я заранее не знаю какой именно мне нужен будет? А вот про енто можно поподробнее или вообще как в кодах будет выглядеть? smile 

Я так понял: у меня сейчас такая структура: (все соотв. через методы)
"Исходный" класс
"Коннект" класс
Класс достающий данные

В исходном классе вызываю Коннект класс -> получаю коннекты -> вызываю класс достающий данные, передовая ему коннекты.

А ты предлаагешь: Исходный класс, в нем вызываю класс достающий данные -> в классе достающий данные по мере необходимости вызываю класс Коннект, получая нужный коннект? 

Это сообщение отредактировал(а) Bulat - 6.7.2006, 13:06


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
carper
Дата 6.7.2006, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 1
Всего: 8



Bulat
"Даже если я заранее не знаю какой именно мне нужен будет? А вот про енто можно поподробнее или вообще как в кодах будет выглядеть?"

Беда в том, что я никак не могу понять суть проблемы.  smile 

Ну обратились мы за произвольным коннектом к фабрике коннектов, ну не "Шмогла она" выдать желаемое, в чем здесь проблема?

Наш класс получит соотв. код возврата или, что разумнее, исключение, обработает его и сам решит может он жить без этого коннекта или нет, например, не попытаться ли ему обратиться к другой базе (впрочем, такой алгоритм - "поиск доступной базы", лучше возложить на фабрику соединений).

 smile 
Поскольку не думаю, что проблема настолько проста, то полезно было бы глянуть на кастрированный код класса, который вызывает проблему (только обязательно кастрированный много строк не имеющих отношения к делу не осилю smile )  с указанием проблемных мест.

 
PM MAIL   Вверх
chief39
Дата 6.7.2006, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


карманная тигра
***


Профиль
Группа: Участник Клуба
Сообщений: 1631
Регистрация: 20.5.2005
Где: Киев

Репутация: 15
Всего: 77



Опиши реальную ситуацию.
А то "с одной базой поработал - в зависимости от результатов то ко второй то к третьей коннектиться, если не законектился - то она мне и не нужна, а нужна другая.."
"Песца на снегу не видно. Белый песец, белый снег — писец, ничего не понятно."(с)
Ты на пальцах покажи, конец дня всё-таки.... не железные же smile

Покажи - там сконнетился- считал то, в той базе хранится то, в это - не то. тут вообще нихрена не хранится, а этой базы ваще нет
Хоть по именам их обзови smile
 


--------------------
Люди - это свечи. Они либо горят, либо их - в жопу!(с)

PM MAIL   Вверх
Bulat
Дата 7.7.2006, 07:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 4
Всего: 57



ОК, тока енто все равно не раскроет все моменты, потому что комбинаций коннектов много, в базе хранится куча всего, запросы очень разные. А база составлена так, что в одной первоначальная инфа по всем. В другой уже по некоторым определенным клиентам одного рода(таких несколько), в третьей по другим параметрам одни клиенты, везде данные разные. (Но логически база составлена грамотно, просто так тоже не обьяснишь, либо ряд постов и на это тратить придется)
вот класс где коннекты:
Код

public class Connect {

    public Connection init_hh() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
        String databaseurl = "...",
                      user = "...",
                  password = "...",
                driverName = "com.mysql.jdbc.Driver";
        Class.forName(driverName).newInstance();
        Connection con = DriverManager.getConnection(databaseurl, user, password);
        return con;
    }

    public Connection init_c() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
         String databaseurl = "...",
                       user = "...",
                   password = "...",
                 driverName = "com.mysql.jdbc.Driver";
        Class.forName(driverName).newInstance();
        Connection con = DriverManager.getConnection(databaseurl, user, password);
        return con;
    }

    public Connection init_p() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
        String databaseurl = "...",
                      user = "...",
                  password = "...",
                driverName = "com.mysql.jdbc.Driver";
        Class.forName(driverName).newInstance();
        Connection con = DriverManager.getConnection(databaseurl, user, password);
        return con;
    }

...

    public void destroy_hh (Connection con_hh) {
        try {
            con_hh.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void destroy_c (Connection con_c) {
        try {
            con_c.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void destroy_p (Connection con_p) {
        try {
            con_p.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}


Вот как я его применяю
Код

...
                    Connect connect = new Connect();
                    try {
                        con_hh = connect.init_hh();
                        con_c = connect.init_c();
                        con_p = connect.init_p();
                        FindByUserId fbui = new FindByUserId(userId, con_hh, con_c, con_p);
                        FindData[] buidArray = fbui.getIpClientData();
                        ...
                        connect.destroy_p(con_p);
                        connect.destroy_c(con_c);
                        connect.destroy_hh(con_hh);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
...


Вот один из тех классов где мне нужны коннекты.
Код

public class FindByUserId {
    private Integer userId;
    private Connection con_hh, con_c, con_p;

    public FindByUserId(Integer userId, Connection con_hh, Connection con_c, Connection con_p) {
        this.userId = userId;
        this.con_hh = con_hh;
        this.con_c = con_c;
        this.con_p = con_p;
    }

    public FindData[] getIpClientData() throws SQLException {
        List BUIdata = new ArrayList();
        Statement st_c = con_c.createStatement();
        PreparedStatement pst_c = con_c.prepareStatement("SELECT user_name, flag, balance, record_id FROM Records LEFT JOIN Users ON (user_id = id) WHERE user_id = ? AND ((flag&0) or (flag&1) or (flag&8))") ;
        pst_c.setInt(1, userId);
        ResultSet rs_c = pst_c.executeQuery();
        while (rs_c.next()) {
            if (rs_c.getInt("flag") == 1) {
                if (userId == 21782) {
                    Statement st_hh = con_hh.createStatement();
                    PreparedStatement pst_hh = con_hh.prepareStatement("SELECT record_id, login_id, pin, balance FROM Logins WHERE user_id = ? AND record_id = ?");
                    pst_hh.setInt(1, userId);
                    pst_hh.setInt(2, rs_c.getInt("record_id"));
                    ResultSet rs_hh = pst_hh.executeQuery();
                    while (rs_hh.next()) {
                        FindData element = new FindData(userId, rs_hh.getInt("record_id"), rs_hh.getInt("login_id"), rs_c.getString("user_name"), rs_hh.getString("pin"), rs_hh.getDouble("balance"));
                        BUIdata.add(element);
                    }
                    rs_hh.close();
                    pst_hh.close();
                    st_hh.close();
                } else {
                    Statement st_hh = con_hh.createStatement();
                    PreparedStatement pst_hh = con_hh.prepareStatement("SELECT record_id, login_id, pin, balance FROM Logins WHERE user_id = ?");
                    pst_hh.setInt(1, userId);
                    ResultSet rs_hh = pst_hh.executeQuery();
                    while (rs_hh.next()) {
                        FindData element = new FindData(userId, rs_hh.getInt("record_id"), rs_hh.getInt("login_id"), rs_c.getString("user_name"), rs_hh.getString("pin"), rs_hh.getDouble("balance"));
                        BUIdata.add(element);
                    }
                    rs_hh.close();
                    pst_hh.close();
                    st_hh.close();
                }
            } else if (rs_c.getInt("flag") == 8) {
                Statement st_p = con_p.createStatement();
                PreparedStatement pst_p = con_p.prepareStatement("SELECT record_id, login_id, ip_address FROM Logins WHERE user_id = ?");
                pst_p.setInt(1, userId);
                ResultSet rs_p = pst_p.executeQuery();
                while (rs_p.next()) {
                    PreparedStatement pst_p1 = con_p.prepareStatement("SELECT INET_NTOA(ip_address) FROM Logins WHERE login_id = ?");
                    pst_p1.setInt(1, rs_p.getInt("login_id"));
                    ResultSet rs_p1 = pst_p1.executeQuery();
                    while (rs_p1.next()) {
                        String ip_adr = String.valueOf(rs_p1.getString("INET_NTOA(ip_address)"));
                        FindData element = new FindData(userId, rs_p.getInt("record_id"), rs_p.getInt("login_id"), rs_c.getString("user_name"), ip_adr, rs_c.getDouble("balance"));
                        BUIdata.add(element);
                    }
                }
                rs_p.close();
                pst_p.close();
                st_p.close();
            }
        }
        ...
        rs_c.close();
        pst_c.close();
        st_c.close();
        return (FindData[]) BUIdata.toArray(new FindData[BUIdata.size()]);
    }

}


Как видно один коннект мне стабильно нужен, но остальные по мере необходимости, в зависимости от того какой клиент(группа клиентов) и какая инфа о нем нужна. (хотелось бы чтобы приложение все же выполняло не определенные задачи, а в определенной мере было универсальным, сорри за тавтологию)

Единственное возможно лучшее решение, это как я раньше уже писал, не передовать сразу все коннекты, а вызывать их по мере необходимости и в этот момент проверять/обрабатывать. Увеличит объем кода, но пока я только так вижу оптимальный выход из ситуации.


chief39, я обычно сюда по утрам, в обед лазию. Потому как понял что вечером здесь от меня мало толку. 


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
carper
Дата 7.7.2006, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 1
Всего: 8



Цитата(Bulat @  7.7.2006,  07:53 Найти цитируемый пост)
Единственное возможно лучшее решение, это как я раньше уже писал, не передовать сразу все коннекты, а вызывать их по мере необходимости и в этот момент проверять/обрабатывать. Увеличит объем кода, но пока я только так вижу оптимальный выход из ситуации.


Вполне нормальное решение, объем кода это никак не увеличит, разве что вместо обращения к переменной класса будет обращение к методу, ну, и в конце всех if-ов добавиться маленький блочок обработки универсального исключения (см. ниже).

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

IMHO составление списка готовых коннектов "про запас" в данном случае не нужно.

Код

Connect connect = new Connect();
               try {
                        FindByUserId fbui = new FindByUserId(userId, connect);
                        FindData[] buidArray = fbui.getIpClientData();
                        ...
                     } catch (myDBError e) {
                        e.printFullErrorDescription();
                    }//end try




Код

  private Integer userId;
    private Connect con;

   //Смысл этого метода из примера темен и неясен, но не в нем суть.
    public FindByUserId(Integer userId, Connect Con) {
        this.userId = userId;        
        con= Con;
     }


public FindData[] getIpClientData() throws  myDBError { 
        List BUIdata = new ArrayList();
      Connect con_c, con_hh ....
 try {
        Connect con_c= con.get_YOUR_CONNECTION(Type_YOUR_CONNECTION);
        Statement st_c = con_c.createStatement();
        PreparedStatement pst_c = con_c.prepareStatement(
        ..................
    
        while (rs_c.next()) {
            if (rs_c.getInt("flag") == 1) {
                if (userId == 21782) {
                    if(con_hh == null) { //Ну нужна ли тут эта проверка сами думайте, меня смутил while - если
                                                     //этот блок выполняется несколько раз, то это имеет смысл, иначе 
                                                     //незачем - решайте уж сами                                                  
                       con_hh=con.get_YOUR_CONNECTION(Type_YOUR_CONNECTION); 
                    }
                    Statement st_hh = con_hh.createStatement();
                    PreparedStatement pst_hh = con_hh.prepareStatement(
        ...................................
catch (SQLError e) {
   ... // см. ниже
}
catch (myDBError e) {
    //Тут, если хотим, как-то предварительно обрабатываем ошибку и отбрасываем ее снова (при  необходимости)
    con.freeConnections(); /*Ну, или что там нужно сделать с вновь созданными соединеними пусть решает
                                         класс ответственный за пул соединений, лучше там держать логику обработки 
открытых соединений и подсчет числа коннектов, чем передавать ему открытые соединения, но ежели 
неохота, то просто накапливаем список наших соединений в массиве и передаем для обработки калссу - пуллу соединений. */
}//end try
 con.freeConnections(); 
        return (FindData[]) BUIdata.toArray(new FindData[BUIdata.size()]);
       
    }

}



 
PM MAIL   Вверх
Bulat
Дата 7.7.2006, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 4
Всего: 57



carper, ну в принципе мой алгоритм, тока в деталях немного другой smile 

Цитата(carper @  7.7.2006,  08:48 Найти цитируемый пост)
Код можно подсократить, обрабатывая все основные исключения в классе коннектов, который будет, в свою очередь отбрасывать только одно, собственное, исключение с подробным описанием ошибки.

Вот за это пасиба, хоть мне это не совсем подходит(там есть еще и другие заморочки), но можно кое куда впихнуть smile 
 


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
chief39
Дата 7.7.2006, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


карманная тигра
***


Профиль
Группа: Участник Клуба
Сообщений: 1631
Регистрация: 20.5.2005
Где: Киев

Репутация: 15
Всего: 77



А почему бы не сделать классец, который будет содержать в себе:
-  полученные коннекты
-  методы их инита
-  методы клоза

То есть доработать класс Connect 

И создавая его - ничего не получать из пула.
Передавать его вместо списка коннектов.
И получать из него через GetConnection(String ID) коннекшн конкретного типа.
то есть в момент вызова этого метода - получать коннекшн если он ещё не получен, сохранять его в переменной(хэшмэпе ссылок на коннекшны по имени) класса и выделять наверх, уже для использования.
Там(в классе) и делать обработку всех иксепшнов.

И сделать  close() в этом классе, который будет закрывать все открытые до того коннекшны.
Кстати, такой клоз или такие
Цитата(Bulat @  7.7.2006,  07:53 Найти цитируемый пост)
        rs_c.close();
        pst_c.close();
        st_c.close();

клозы стоит заносить в finally блок, а не оставлять просто в конце метода

 


--------------------
Люди - это свечи. Они либо горят, либо их - в жопу!(с)

PM MAIL   Вверх
kondr
Дата 13.7.2006, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 24.11.2005

Репутация: нет
Всего: 1



Я вообще в Java не большой спец, но здесь по-моему явно плохой дизайн и из-за этого все проблемы. У тебя три класса инита, три класса дестроя с одинаковым кодом и т.п. Почему бы их не вынести в базовый класс? Короче надо сделать базовый класс конекта и три потомка для соединения с каждой базой.  
PM MAIL   Вверх
Bulat
Дата 20.7.2006, 07:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 4
Всего: 57



kondr, такая реализация не решает суть самой проблемы smile И даже мне кажется есть моменты когда усложняет, если принять во внимание то, что я коннектюсь к разным сервакам, а не к разным БД, на одном сервере  


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
chief39
Дата 20.7.2006, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


карманная тигра
***


Профиль
Группа: Участник Клуба
Сообщений: 1631
Регистрация: 20.5.2005
Где: Киев

Репутация: 15
Всего: 77



Цитата(Bulat @  20.7.2006,  07:41 Найти цитируемый пост)
если принять во внимание то, что я коннектюсь к разным сервакам, а не к разным БД, на одном сервере   

А какая разница для реализации? smile
УРЛЫ коннектов всё равно разные в этих двух случаев у разных БД.
С программной т.з. - джидибиси пофик тут же база или на дргуом серваке 


--------------------
Люди - это свечи. Они либо горят, либо их - в жопу!(с)

PM MAIL   Вверх
Bulat
Дата 20.7.2006, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 4
Всего: 57



Тема пока себя изжила, конкретно для меня, у меня пока поставились другие задачи, может скоро вернусь. Да и кроме того я наконец добрался до hibernate  smile  


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0980 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.