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

anna

Lotus team
03.06.2014
400
7
#1
Код:
qry.SQL =query$
Set res.Query = qry
res.CacheLimit=DB_NONE
res.Execute
Print res.NumRows
выдает -1
А при дальнейшем переборе
Код:
res.FirstRow
Call DoCompare()
Do
res.NextRow
Call DoCompare()
Loop Until res.IsEndOfData
набор строк нормально отдается.

Что случилось с numrows?
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 567
263
#3
ОДБЦ, насколько помню, может иметь опцию не грузить все выборку и, очевидно, не знать кол-во строк
 

anna

Lotus team
03.06.2014
400
7
#4
И что же делать? Может, тогда и вторая часть приведенного кода тоже не все отдает?
 

anna

Lotus team
03.06.2014
400
7
#7
Да, я уже и сама поняла, что нужно попробовать уйти на 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 и работа с выборкой? пожааалуйста, а то я сейчас ну все грабли переберу какие можно.
 

oshmianski

Достойный программист
Lotus team
25.04.2012
552
8
#8
Создаете 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.
 

anna

Lotus team
03.06.2014
400
7
#9
1) А что с переменной driver? Не вижу, где к ней идет обращение.
2) Освобождать ресурсы - это как?
3) Как в JDBC контролировать окончание выполнения запроса?
4) Нужно ли назначать размеры кэша?
5) Можно ли пример на работу с сетом данных select?

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

anna

Lotus team
03.06.2014
400
7
#10
Объясните мне тупой - что я делаю не так.
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)
Код:
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("Драйвер подключен");
А выдает:
Код:
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)
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 567
263
#11
3) До кучи (раз я не понимаю, что такое classpath), прописаны переменные среды пользователя CLASSPATH C:\Program Files\Microsoft SQL Server JDBC Driver 3.0\sqljdbc.jar
в кавычках?

2) В эклипсе в Project/Properties/JavaBuildPath/Libraries/AddExternalJars эти жарники указаны
это д.б. достаточно для эклипсового проекта, но нотусня как себя поведет - ХЗ

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

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

garrick

Lotus team
26.10.2009
894
61
#12
Объясните мне тупой - что я делаю не так.
1) sqljdbc.jar и sqljdbc4.jar лежат в C:\Program Files\Microsoft SQL Server JDBC Driver 3.0
Положите эти файлы в C:\Program Files\IBM\Lotus\Notes\jvm\lib\ext\, если у вас Lotus Notes установлен по этому пути. Если нет, скорректируйте путь до папки jvm под ваш. Если будете потом запускать этот агент на сервере, не забудьте положить и туда. Можно "интегировать" jar файлы непосредственно в агента, но будут проблемы в высвобождением памяти.
3) До кучи (раз я не понимаю, что такое classpath), прописаны переменные среды пользователя CLASSPATH
Забудьте про CLASSPATH в контексте Lotus Notes - это работает только в самостоятельных Java приложениях, для лотусовых агентов и библиотек это не работает.

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

garrick

Lotus team
26.10.2009
894
61
#13
2) Освобождать ресурсы - это как?
Не забывайте своевременно вызывать метод close() для ResultSet, Statement, Connection и прочих JDBC объектов. Иначе у вас случится какая-нибудь неприятность типа превышения лимита количества подключений к серверу базы данных, если ваш агент не умрёт раньше от потери памяти. :)
5) Можно ли пример на работу с сетом данных select?
Для просмотра контента необходимо: Войти или зарегистрироваться
такой учебник подойдёт? Там вроде всё есть, например
Для просмотра контента необходимо: Войти или зарегистрироваться
 

oshmianski

Достойный программист
Lotus team
25.04.2012
552
8
#14
1) А что с переменной driver? Не вижу, где к ней идет обращение.
Java:
...
try {
Class.forName(driver);//Регистрируем драйвер
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
 
Connection c = null;//Соединение с БД
try{
c = DriverManager.getConnection(url, user, password);
...
3) Как в JDBC контролировать окончание выполнения запроса?
А зачем его контролировать?

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

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


5) Можно ли пример на работу с сетом данных select?
Вот на скорую руку:
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) {
}
}
}
}
 

anna

Lotus team
03.06.2014
400
7
#15
Предлагаю перенести обсуждение подключения JDBC в отдельный тред.
А пока по существу вопроса выяснила:
Если пользоваться ODBC, то нужно ждать окончания выполнения запроса, и только потом с ним работать. Это, кажется, называется, асинхронность. Я просто давно на эти грабли не наступала, подзабыла уже.

Делается просто: после Execute передернуть
res.Execute
res.LastRow
таким образом, дождаться последней строки запроса. Затем, самым тупым образом:
Код:
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
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 567
263
#16
PS: с JDBC сделала все, как вы сказали, теперь пишет
Драйвер подключен
java.sql.SQLException: No suitable driver
как? если все положено в jvm/lib/ext - должно находить (причем - никаких вложенных каталогов!)
НО нотус или сервак - надо передернуть