Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Патерн sigleton и подключение к MS SQL


Автор: Alagert 20.4.2006, 20:11
Вот столкнулся с такой проблемой: пишу клиетское приложение для MS SQL server. Подключение к серверу хочу сделать с помощью абстрактного класса, который бы не каждый раз создавался, когда нужно подключение, а получал свою реализацию. Т.е. хочу использовать патерн singleton. Вот код, который, я думал, будет работать.
Код

package com.alagert.mssql.db;
import java.sql.*;

public    abstract class DBConnection {
    private Connection conn=null;
    private String serverName;
    private String dbName;
    private String userName;
    private String pass;
    private static DBConnection singleton=null;
    
    static{
        try{
                singleton=(DBConnection)Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();//тут ошибка
        }
        catch (ClassNotFoundException ex){
            System.out.println(ex.getLocalizedMessage());
        }
        catch(IllegalAccessException ex){}
        catch(InstantiationException ex){}
    }
    
    public DBConnection(){
        
    }
    
    public Connection installConn(String serverName,String dbName,String userName,String pass){
        if(conn==null){
            this.serverName=serverName;
            this.dbName=dbName;
            this.userName=userName;
            this.pass=pass;
            String strCon="jdbc:microsoft:sqlserver://"+this.serverName+":1433;databaseName="+this.dbName+";";
            try{
                conn = DriverManager.getConnection(strCon,this.userName,this.pass);
            }catch(SQLException ex){
                System.out.println(ex.getLocalizedMessage());
            }
        }
        return conn;
    }
    
    public static DBConnection getInstance(){
        if(singleton == null)
            throw new IllegalStateException("DBConnection init failed");
        return singleton;
    }
}


Соответсвенно натолкнулся на грабли. По тому как 
Код

Cllss.forName(...).newInstance();

возвращает Class. Происходит ошибка инициализации.

Народ помогите Плиз, подскажите как мне правильно использовать данную стратегию? 

И расскажите: как наиболее часто пишуться подключения к БД?

Всем спасибо.

Автор: LSD 20.4.2006, 20:21
Такой код:
Код
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance()

вернет тебе екземпляр драйвера SQL Server-а, а не твой класс. Тебе надо создать не абстрактную реализацию твоего класса DBConnection, и получать ее:
Код
Class.forName("DBConnectionImpl").newInstance()
 

Автор: Alagert 20.4.2006, 20:28
Я так понимаю 
Код

Class.forName("DBConnection").newInstance();

я должен присвоить моему синглтону?
При этом в статической часте моего класса оставить 
Код

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance()


Правильно?

И как обычно пишуться подключения к базам? 

Автор: LSD 20.4.2006, 20:39
Цитата(Alagert @  20.4.2006,  21:28 Найти цитируемый пост)
я должен присвоить моему синглтону?

Только не
Код
Class.forName("DBConnection").newInstance();

а
Код
Class.forName("DBConnectionImpl").newInstance();

т.к. DBConnection абстрактный и создать его экземпляр не получится.


Цитата(Alagert @  20.4.2006,  21:28 Найти цитируемый пост)
И как обычно пишуться подключения к базам? 

Зависит от условий задачи. Если тебе надо много соединений, то надо использовать пул. Если же это обычное клиентское приложение, то можно обойтись и одним.
Можно например считать пареметры соединения из конфигурационного файла, а потом просто:
Код
private static Connection connection;

public static Connection getConnection() throws SQLException, ClassNotFoundException
{
  if(connection == null)
  {
    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
    connection = DriverManager.getConnection("url", "user", "password");
  }
  return connection;
}
  
public static void closeConnection() throws SQLException
{
  if(connection != null)
  {
    connection.close();
    connection = null;
  }
}
 

Автор: Alagert 20.4.2006, 21:19
LSD, пасибо большое.

А если сдеалть так:
Код

package com.alagert.mssql.db;
import java.sql.*;

public class DBConnection {
    private Connection conn=null;
    private String serverName;
    private String dbName;
    private String userName;
    private String pass;
    private static DBConnection singleton=null;
    
    static{
        try{
            Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
            singleton=(DBConnection)Class.forName("DBConnection").newInstance();
        }
        catch (ClassNotFoundException ex){
            System.out.println(ex.getLocalizedMessage());
        }
        catch(IllegalAccessException ex){}
        catch(InstantiationException ex){}
    }
    
    public DBConnection(){
        
    }
    
    public Connection installConn(String serverName,String dbName,String userName,String pass){
        if(conn==null){
            this.serverName=serverName;
            this.dbName=dbName;
            this.userName=userName;
            this.pass=pass;
            String strCon="jdbc:microsoft:sqlserver://"+this.serverName+":1433;databaseName="+this.dbName+";";
            try{
                conn = DriverManager.getConnection(strCon,this.userName,this.pass);
            }catch(SQLException ex){
                System.out.println(ex.getLocalizedMessage());
            }
        }
        return conn;
    }
    
    public static DBConnection getInstance(){
        if(singleton == null)
            throw new IllegalStateException("DBConnection init failed");
        return singleton;
    }
}


то не вызывается статический инициализатор. Почему?  

Автор: LSD 20.4.2006, 21:48
Потому что ты пытаешься загрузить класс DBConnection, а у тебя на самом деле класс com.alagert.mssql.db.DBConnection. Java всегда оперирует полными именами классов.

Кстати почему ты не заменишь:
Код
singleton = (DBConnection)Class.forName("DBConnection").newInstance();

на
Код
singleton = new DBConnection();

? 

Автор: Beard 21.4.2006, 11:31
Уж раз у тебя singleton, то конструктор надо сделать private.  

Автор: Alagert 22.4.2006, 22:10
Цитата(LSD @  20.4.2006,  21:48 Найти цитируемый пост)
Потому что ты пытаешься загрузить класс DBConnection, а у тебя на самом деле класс com.alagert.mssql.db.DBConnection. Java всегда оперирует полными именами классов.

После исправления этого, все заработала. Большое спаисбо. А контруктор в статическом инициализатор вызывать нельзя.
Цитата(Beard @  21.4.2006,  11:31 Найти цитируемый пост)
Уж раз у тебя singleton, то конструктор надо сделать private.   

Пасибо за замечание.

Подскажите плиз хорошие книжки, где можно почитать про реализацию различных патернов на Java. 

Всем спасибо.
 

Автор: LSD 22.4.2006, 22:23
Цитата(Alagert @  22.4.2006,  23:10 Найти цитируемый пост)
Подскажите плиз хорошие книжки, где можно почитать про реализацию различных патернов на Java. 

http://www.natahaus.ru/2006/01/23/primenenie_shablonov_Java.html.
А вообще посмотри в http://forum.vingrad.ru/index.php?showforum=150, там были еще книги по шаблонам проектирования. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)