Решено Mssql через odbc - не отдается кол-во строк

Тема в разделе "Lotus - Программирование", создана пользователем anna, 18 июн 2015.

  1. anna

    anna Lotus team
    Lotus team

    Регистрация:
    3 июн 2014
    Сообщения:
    312
    Симпатии:
    8
    Код (Text):
    qry.SQL =query$
    Set res.Query = qry
    res.CacheLimit=DB_NONE
    res.Execute
    Print res.NumRows
    выдает -1
    А при дальнейшем переборе
    Код (Text):
    res.FirstRow
    Call DoCompare()
    Do
    res.NextRow
    Call DoCompare()
    Loop Until res.IsEndOfData
    набор строк нормально отдается.

    Что случилось с numrows?
     
  2. Shandrik

    Shandrik Well-Known Member

    Регистрация:
    30 дек 2010
    Сообщения:
    236
    Симпатии:
    24
    А код ждет, пока Execute выполнится?
     
  3. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
    ОДБЦ, насколько помню, может иметь опцию не грузить все выборку и, очевидно, не знать кол-во строк
     
  4. anna

    anna Lotus team
    Lotus team

    Регистрация:
    3 июн 2014
    Сообщения:
    312
    Симпатии:
    8
    И что же делать? Может, тогда и вторая часть приведенного кода тоже не все отдает?
     
  5. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
  6. oshmianski

    oshmianski Достойный программист
    Lotus team

    Регистрация:
    25 апр 2012
    Сообщения:
    521
    Симпатии:
    13
    использовать JDBC?
     
  7. anna

    anna Lotus team
    Lotus team

    Регистрация:
    3 июн 2014
    Сообщения:
    312
    Симпатии:
    8
    Да, я уже и сама поняла, что нужно попробовать уйти на JDBC.

    Вот скачала драйвер JDBC, распаковала его куда нужно. А далее нужно
    The following is an example of the CLASSPATH statement that is used for a Windows application:
    CLASSPATH =.;C:\Program Files\Microsoft SQL Server JDBC Driver\sqljdbc_3.0\enu\sqljdbc.jar

    это нужно добавить переменную Classpath в enviroment? (винда)
    А далее что в агенте прописывать?

    И потом - там обращение к серверу выглядит как String connectionUrl = "jdbc:sqlserver://localhost:1433;" +
    "databaseName=AdventureWorks;user=MyUserName;password=*****;";
    Connection con = DriverManager.getConnection(connectionUrl);

    порт у всех 1433?
    можно примитивный образец подключения к mssql и работа с выборкой? пожааалуйста, а то я сейчас ну все грабли переберу какие можно.
     
  8. oshmianski

    oshmianski Достойный программист
    Lotus team

    Регистрация:
    25 апр 2012
    Сообщения:
    521
    Симпатии:
    13
    Создаете java агента.
    Импортируете архив - жарник mysql-connector-java-хххх-bin.jar.
    Код агента приблизительно такой:
    Код (Java):
    public class JavaAgent extends AgentBase {
     
    public void NotesMain() {
     
    try {
    Session session = getSession();
    AgentContext agentContext = session.getAgentContext();
     
    String user = "";//Логин пользователя
    String password = "";//Пароль пользователя
    String url = "jdbc:mysql://host:port/db_name";//URL адрес
    String driver = "com.mysql.jdbc.Driver";//Имя драйвера
     
    Database db = agentContext.getCurrentDatabase();
    ...
     
    Connection c = null;//Соединение с БД
    try{
    c = DriverManager.getConnection(url, user, password);
    String query = "" +
    "insert into phones (id, number, fio)" +
    " values " +
    "(null, ? , ?)";
    PreparedStatement preparedStmt = c.prepareStatement(query);
    ...
    preparedStmt.setString(1, number);
    preparedStmt.setString(2, fio);
    preparedStmt.execute();
    ...
     
    и не забывайте освобождать ресурсы jdbc.
     
  9. anna

    anna Lotus team
    Lotus team

    Регистрация:
    3 июн 2014
    Сообщения:
    312
    Симпатии:
    8
    1) А что с переменной driver? Не вижу, где к ней идет обращение.
    2) Освобождать ресурсы - это как?
    3) Как в JDBC контролировать окончание выполнения запроса?
    4) Нужно ли назначать размеры кэша?
    5) Можно ли пример на работу с сетом данных select?

    Имя драйвера - имя jar, каторый лежит в C:\Program Files\Microsoft SQL Server JDBC Driver 3.0\ ?
    Еще раз имею наглость спросить - как правильно прописать его в переменные окружения?
     
  10. anna

    anna Lotus team
    Lotus team

    Регистрация:
    3 июн 2014
    Сообщения:
    312
    Симпатии:
    8
    Объясните мне тупой - что я делаю не так.
    1) sqljdbc.jar и sqljdbc4.jar лежат в C:\Program Files\Microsoft SQL Server JDBC Driver 3.0
    2) В эклипсе в Project/Properties/JavaBuildPath/Libraries/AddExternalJars эти жарники указаны.
    3) До кучи (раз я не понимаю, что такое classpath), прописаны переменные среды пользователя CLASSPATH C:\Program Files\Microsoft SQL Server JDBC Driver 3.0\sqljdbc.jar
    4)
    Код (Text):
    String user = "";//Логин пользователя
              String password = "";//Пароль пользователя
              String url = "jdbc:mysql://1.1.2.2:1433/TEST";//URL адрес
              String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";//Имя драйвера
              Class.forName(driver);
              System.out.println("Драйвер подключен");
    А выдает:
    Код (Text):
    java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
    at java.lang.Class.forNameImpl(Native Method)
    at java.lang.Class.forName(Class.java:182)
    at JavaAgent.NotesMain(Unknown Source)
    at lotus.domino.AgentBase.runNotes(Unknown Source)
    at lotus.domino.NotesThread.run(Unknown Source)
     
  11. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
    в кавычках?

    это д.б. достаточно для эклипсового проекта, но нотусня как себя поведет - ХЗ

    если для агента - то в нем надо указать либы (а не в общем окружении) - Import Archive

    [DOUBLEPOST=1434641950,1434641897][/DOUBLEPOST]системный CLASSPATH для нотуса не указ (для его агентов используется свой механизм)
    [DOUBLEPOST=1434642155][/DOUBLEPOST]самый "простой" способ для разработки и размещения на сервере - это положить jar-ы в jvm/lib/ext
    сервер/клиент, при этом, надо передернуть
     
  12. garrick

    garrick Lotus team
    Lotus team

    Регистрация:
    26 окт 2009
    Сообщения:
    773
    Симпатии:
    52
    Положите эти файлы в C:\Program Files\IBM\Lotus\Notes\jvm\lib\ext\, если у вас Lotus Notes установлен по этому пути. Если нет, скорректируйте путь до папки jvm под ваш. Если будете потом запускать этот агент на сервере, не забудьте положить и туда. Можно "интегировать" jar файлы непосредственно в агента, но будут проблемы в высвобождением памяти.
    Забудьте про CLASSPATH в контексте Lotus Notes - это работает только в самостоятельных Java приложениях, для лотусовых агентов и библиотек это не работает.

    P.S. CLASSPATH - это переменная окружения, которая указывает Java приложению где можно поискать необходимые для запуска и работы библиотеки и классы.
     
  13. garrick

    garrick Lotus team
    Lotus team

    Регистрация:
    26 окт 2009
    Сообщения:
    773
    Симпатии:
    52
    Не забывайте своевременно вызывать метод close() для ResultSet, Statement, Connection и прочих JDBC объектов. Иначе у вас случится какая-нибудь неприятность типа превышения лимита количества подключений к серверу базы данных, если ваш агент не умрёт раньше от потери памяти. :)
    JDBC Basics такой учебник подойдёт? Там вроде всё есть, например Retrieving and Modifying Values from Result Sets
     
  14. oshmianski

    oshmianski Достойный программист
    Lotus team

    Регистрация:
    25 апр 2012
    Сообщения:
    521
    Симпатии:
    13
    Код (Java):

    ...
    try {
    Class.forName(driver);//Регистрируем драйвер
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
     
    Connection c = null;//Соединение с БД
    try{
    c = DriverManager.getConnection(url, user, password);
    ...
     
    А зачем его контролировать?

    Конкретно у MSSQL не знаю, у h2 точно есть, ибо работал. Думаю опция есть, но умолчального значения должно хватать.

    Как верно заметили коллеги, в переменную окружения jar-ки прописывать не нужно. Их достаточно импортировать в агент (в общем случае) или положить в ...\jvm\lib\ext клиента\сервера (что безопаснее, но трудоемнее).


    Вот на скорую руку:
    Код (Java):
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
     
    import lotus.domino.*;
     
    public class JavaAgent extends AgentBase {
     
    public void NotesMain() {
     
    try {
    String user = "";//Логин пользователя
    String password = "";//Пароль пользователя
    String url = "jdbc:mysql://host:port/table_name";//URL адрес
    String driver = "com.mysql.jdbc.Driver";//Имя драйвера
     
    try {
    Class.forName(driver);//Регистрируем драйвер
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
     
    Connection conn = null;
    PreparedStatement stat = null;
    ResultSet rs = null;
    try{
    conn = DriverManager.getConnection(url, user, password);
    String query = "select id, number, fio from phones";
    stat = conn.prepareStatement(query);
     
    rs = stat.executeQuery();
    int count = 0;
    while (rs.next()) {
    count++;
    doSome(rs, count);
    }
     
    } catch(Exception e){
    e.printStackTrace();
    } finally{
    closeDbResources(conn, stat, rs);
    }
    } catch(Exception e) {
    e.printStackTrace();
    }
    }
     
    private void doSome(ResultSet resultSet, int count) throws SQLException{
    System.out.println(count);
    System.out.println("id: " + resultSet.getString("id"));
    System.out.println("phone: " + resultSet.getString("number"));
    System.out.println("fio: " + resultSet.getString("fio"));
    System.out.println("---------------");
    }
     
    private void closeDbResources(Connection connection, Statement statement, ResultSet resultSet) {
    closeResultSet(resultSet);
    closeStatement(statement);
    closeConnection(connection);
    }
     
    private void closeConnection(Connection connection) {
    if (connection != null) {
    try {
    connection.close();
    } catch (SQLException e) {
    }
    }
    }
     
    private void closeStatement(Statement statement) {
    if (statement != null) {
    try {
    statement.close();
    } catch (SQLException e) {
    }
    }
    }
     
    private void closeResultSet(ResultSet resultSet) {
    if (resultSet != null) {
    try {
    resultSet.close();
    } catch (SQLException e) {
    }
    }
    }
    }
     
  15. anna

    anna Lotus team
    Lotus team

    Регистрация:
    3 июн 2014
    Сообщения:
    312
    Симпатии:
    8
    Предлагаю перенести обсуждение подключения JDBC в отдельный тред.
    А пока по существу вопроса выяснила:
    Если пользоваться ODBC, то нужно ждать окончания выполнения запроса, и только потом с ним работать. Это, кажется, называется, асинхронность. Я просто давно на эти грабли не наступала, подзабыла уже.

    Делается просто: после Execute передернуть
    res.Execute
    res.LastRow
    таким образом, дождаться последней строки запроса. Затем, самым тупым образом:
    Код (Text):
    For z = 1 To res.NumRows
    res.CurrentRow = i
    <действия со строками>
    i=i+1
    Next
    И главное, ребятки, убрать res.CacheLimit=DB_ALL, потому как с ним выдается одно и то же вместо разных строк.
    это есть в DesignerHelp "Examples: CurrentRow property"
    У меня все, пасиба.
    PS: с JDBC сделала все, как вы сказали, теперь пишет
    Драйвер подключен
    java.sql.SQLException: No suitable driver
     
  16. lmike

    lmike нет, пердело совершенство
    Команда форума Lotus team

    Регистрация:
    27 авг 2008
    Сообщения:
    6.081
    Симпатии:
    300
    как? если все положено в jvm/lib/ext - должно находить (причем - никаких вложенных каталогов!)
    НО нотус или сервак - надо передернуть
     
Загрузка...

Поделиться этой страницей