resultset.absolute(1)后用resultset.next()为什么总是取不到第一行数据

resultset.absolute(1)后用resultset.next()为什么总是取不到第一行数据,第1张

for(int j=0;j<pgetPagesize()&&rsnext();j++)错了, 这样rs就自动向下移动了, 应该是rshasNext(),表示是否有值。土咖网欢迎你

可以联系我,给你jxljar

========================

jxljar

开放分类: java

通过java *** 作excel表格的工具类库

支持Excel 95-2000的所有版本

生成Excel 2000标准格式

支持字体、数字、日期 *** 作

能够修饰单元格属性

支持图像和图表

应该说以上功能已经能够大致满足我们的需要。最关键的是这套API是纯Java的,并不依赖Windows系统,即使运行在Linux下,它同样能够正确的处理Excel文件。另外需要说明的是,这套API对图形和图表的支持很有限,而且仅仅识别PNG格式。

搭建环境

将下载后的文件解包,得到jxljar,放入classpath,安装就完成了。

基本 *** 作

一、创建文件

拟生成一个名为“测试数据xls”的Excel文件,其中第一个工作表被命名为“第一页”,大致效果如下:

代码(CreateXLSjava):

//生成Excel的类

import javaio;

import jxl;

import jxlwrite;

public class CreateXLS

{

public static void main(String args[])

{

try

{

//打开文件

WritableWorkbook book=

WorkbookcreateWorkbook(new File(“测试xls”));

//生成名为“第一页”的工作表,参数0表示这是第一页

WritableSheet sheet=bookcreateSheet(“第一页”,0);

//在Label对象的构造子中指名单元格位置是第一列第一行(0,0)

//以及单元格内容为test

Label label=new Label(0,0,”test”);

//将定义好的单元格添加到工作表中

sheetaddCell(label);

/生成一个保存数字的单元格

必须使用Number的完整包路径,否则有语法歧义

单元格位置是第二列,第一行,值为789123/

jxlwriteNumber number = new jxlwriteNumber(1,0,789123);

sheetaddCell(number);

//写入数据并关闭文件

bookwrite();

bookclose();

}catch(Exception e)

{

Systemoutprintln(e);

}

}

}

编译执行后,会在当前位置产生一个Excel文件。

二、读取文件

以刚才我们创建的Excel文件为例,做一个简单的读取 *** 作,程序代码如下:

//读取Excel的类

import javaio;

import jxl;

public class ReadXLS

{

public static void main(String args[])

{

try

{

Workbook book=

WorkbookgetWorkbook(new File(“测试xls”));

//获得第一个工作表对象

Sheet sheet=bookgetSheet(0);

//得到第一列第一行的单元格

Cell cell1=sheetgetCell(0,0);

String result=cell1getContents();

Systemoutprintln(result);

bookclose();

}catch(Exception e)

{

Systemoutprintln(e);

}

}

}

程序执行结果:test

四、修改文件

利用jExcelAPI可以修改已有的Excel文件,修改Excel文件的时候,除了打开文件的方式不同之外,其他 *** 作和创建Excel是一样的。下面的例子是在我们已经生成的Excel文件中添加一个工作表:

//修改Excel的类,添加一个工作表

import javaio;

import jxl;

import jxlwrite;

public class UpdateXLS

{

public static void main(String args[])

{

try

{

//Excel获得文件

Workbook wb=WorkbookgetWorkbook(new File(“测试xls”));

//打开一个文件的副本,并且指定数据写回到原文件

WritableWorkbook book=

WorkbookcreateWorkbook(new File(“测试xls”),wb);

//添加一个工作表

WritableSheet sheet=bookcreateSheet(“第二页”,1);

sheetaddCell(new Label(0,0,”第二页的测试数据”));

bookwrite();

bookclose();

}catch(Exception e)

{

Systemoutprintln(e);

}

}

}

三、高级 *** 作

数据格式化

在Excel中不涉及复杂的数据类型,能够比较好的处理字串、数字和日期已经能够满足一般的应用。

1、 字串格式化

字符串的格式化涉及到的是字体、粗细、字号等元素,这些功能主要由WritableFont和WritableCellFormat类来负责。假设我们在生成一个含有字串的单元格时,使用如下语句,为方便叙述,我们为每一行命令加了编号:

WritableFont font1=

new WritableFont(WritableFontTIMES,16,WritableFontBOLD); 或//设置字体格式为excel支持的格式 WritableFont font3=new WritableFont(WritableFontcreateFont("楷体_GB2312"),12,WritableFontNO_BOLD );① WritableCellFormat format1=new WritableCellFormat(font1); ② Label label=new Label(0,0,”data 4 test”,format1) ③ 其中①指定了字串格式:字体为TIMES,字号16,加粗显示。WritableFont有非常丰富的构造子,供不同情况下使用,jExcelAPI的java-doc中有详细列表,这里不再列出。 ②处代码使用了WritableCellFormat类,这个类非常重要,通过它可以指定单元格的各种属性,后面的单元格格式化中会有更多描述。 ③处使用了Label类的构造子,指定了字串被赋予那种格式。 在WritableCellFormat类中,还有一个很重要的方法是指定数据的对齐方式,比如针对我们上面的实例,可以指定:

//把水平对齐方式指定为居中

format1setAlignment(jxlformatAlignmentCENTRE);

//把垂直对齐方式指定为居中

format1setVerticalAlignment(jxlformatVerticalAlignmentCENTRE);

//设置自动换行

format1setWrap(true);

单元格 *** 作

Excel中很重要的一部分是对单元格的 *** 作,比如行高、列宽、单元格合并等,所幸jExcelAPI提供了这些支持。这些 *** 作相对比较简单,下面只介绍一下相关的API。

1、 合并单元格

WritableSheetmergeCells(int m,int n,int p,int q);

作用是从(m,n)到(p,q)的单元格全部合并,比如:

WritableSheet sheet=bookcreateSheet(“第一页”,0);

//合并第一列第一行到第六列第一行的所有单元格

sheetmergeCells(0,0,5,0);

合并既可以是横向的,也可以是纵向的。合并后的单元格不能再次进行合并,否则会触发异常。

2、 行高和列宽

WritableSheetsetRowView(int i,int height);

作用是指定第i+1行的高度,比如:

//将第一行的高度设为200

sheetsetRowView(0,200);

WritableSheetsetColumnView(int i,int width);

作用是指定第i+1列的宽度,比如:

//将第一列的宽度设为30

sheetsetColumnView(0,30);

四、 *** 作

public static void write()throws Exception{

WritableWorkbook wwb=WorkbookcreateWorkbook(new File("c:/1xls"));

WritableSheet ws=wwbcreateSheet("Test Sheet 1",0);

File file=new File("C:\\jbproject\\PVS\\WebRoot\\weekhit\\1109496996281png");

WritableImage image=new WritableImage(1, 4, 6, 18,file);

wsaddImage(image);

wwbwrite();

wwbclose();

}

很简单和插入单元格的方式一样,不过就是参数多了些,WritableImage这个类继承了Draw,上面只是他构造方法的一种,最后一个参数不用了说了,前面四个参数的类型都是double,依次是 x, y, width, height,注意,这里的宽和高可不是的宽和高,而是所要占的单位格的个数,因为继承的Draw所以他的类型必须是double,具体里面怎么实现的我还没细看:)因为着急赶活,先完成功能,其他的以后有时间慢慢研究。以后会继续写出在使用中的心得给大家。

读:

读的时候是这样的一个思路,先用一个输入流(InputStream)得到Excel文件,然后用jxl中的Workbook得到工作薄,用Sheet从工作薄中得到工作表,用Cell得到工作表中得某个单元格

InputStream->Workbook->Sheet->Cell,就得到了excel文件中的单元格

代码:

String path="c:\\excelxls";//Excel文件URL

InputStream is = new FileInputStream(path);//写入到FileInputStream

jxlWorkbook wb = WorkbookgetWorkbook(is); //得到工作薄

jxlSheet st = wbgetSheet(0);//得到工作薄中的第一个工作表

Cell cell=stgetCell(0,0);//得到工作表的第一个单元格,即A1

String content=cellgetContents();//getContents()将Cell中的字符转为字符串

wbclose();//关闭工作薄

isclose();//关闭输入流

我们可以通过Sheet的getCell(x,y)方法得到任意一个单元格,x,y和excel中的坐标对应

例如A1对应(0,0),A2对应(0,1),D3对应(3,2)Excel中坐标从A,1开始,jxl中全部是从0开始

还可以通过Sheet的getRows(),getColumns()方法得到行数列数,并用于循环控制,输出一个sheet中的所有内容

写:

往Excel中写入内容主要是用jxlwrite包中的类

思路是这样的:

OutputStream<-WritableWorkbook<-WritableSheet<-Label

这里面Label代表的是写入Sheet的Cell位置及内容

代码:

OutputStream os=new FileOutputStream("c:\\testxls");//输出的Excel文件URL

WritableWorkbook wwb = WorkbookcreateWorkbook(os);//创建可写工作薄

WritableSheet ws = wwbcreateSheet("sheet1", 0);//创建可写工作表

Label labelCF=new Label(0, 0, "hello");//创建写入位置和内容

wsaddCell(labelCF);//将Label写入sheet中

Label的构造函数Label(int x, int y,String aString)xy意同读的时候的xy,aString是写入的内容

WritableFont wf = new WritableFont(WritableFontTIMES, 12, WritableFontBOLD, false);//设置写入字体

WritableCellFormat wcfF = new WritableCellFormat(wf);//设置CellFormat

Label labelCF=new Label(0, 0, "hello");//创建写入位置,内容和格式

Label的另一构造函数Label(int c, int r, String cont, CellFormat st)可以对写入内容进行格式化,设置字体及其它的属性

现在可以写了

wwbwrite();

写完后关闭

wwbclose();

输出流也关闭吧

osclose;

OK,只要把读和写结合起来,就可以在N个Excel中读取数据写入你希望的Excel新表中,还是比较方便的

下面是程序一例:

程序代码:sql = "select from tablename";

rs = stmtexecuteQuery(sql);

//新建Excel文件

String filePath=requestgetRealPath("aaaxls");

File myFilePath=new File(filePath);

if(!myFilePathexists())

myFilePathcreateNewFile();

FileWriter resultFile=new FileWriter(myFilePath);

PrintWriter myFile=new PrintWriter(resultFile);

resultFileclose();

//用JXL向新建的文件中添加内容

OutputStream outf = new FileOutputStream(filePath);

jxlwriteWritableWorkbook wwb = WorkbookcreateWorkbook(outf);

jxlwriteWritableSheet ws = wwbcreateSheet("sheettest", 0);

int i=0;

int j=0;

for (int k = 0; k < rsgetMetaData()getColumnCount(); k++) {

wsaddCell(new Label(k,0,rsgetMetaData()getColumnName(k+1)));

}

while(rsnext()){

outprintln(rsgetMetaData()getColumnCount());

for (int k = 0; k < rsgetMetaData()getColumnCount(); k++) {

wsaddCell(new Label(k,j+i+1,rsgetString(k+1)));

}

i++;

}

wwbwrite();

wwbclose();

}catch(Exception e){eprintStackTrace();}

finally{

rsclose();

connclose();

}

responsesendRedirect("aaaxls");

jdbc驱动

java jdbc连接_2019最新JDBC面试题(附JDBC教程)

weixin_39665379

关注

0点赞·410人阅读

1什么是JDBC API,何时使用它?

Java DataBase Connectivity API允许我们使用关系数据库。JDBC API接口和类是part javasql和javaxsqlpackage的一部分。我们可以使用JDBC API来获取数据库连接,在数据库服务器中运行SQL查询和存储过程并处理结果。

JDBC API的编写方式允许我们的Java程序和实际的JDBC驱动程序之间的松散耦合,这使我们可以轻松地从一个数据库切换到另一个数据库服务器。

2JDBC驱动程序有哪几种类型?

有四种类型的JDBC驱动程序。任何与数据库一起工作的java程序都有两个部分,第一部分是JDBC API,第二部分是执行实际工作的驱动程序。

JDBC-ODBC Bridge加ODBC驱动程序(类型1):它使用ODBC驱动程序连接到数据库。我们应该安装ODBC驱动程序来连接数据库,这就是为什么这个驱动程序几乎已经过时的原因。

Native API部分支持Java技术的驱动程序(类型2):此驱动程序将JDBC类转换为数据库服务器的客户端API。我们应该安装数据库客户端API。由于对数据库客户端API驱动程序的额外依赖性,这也不是首选驱动程序。

用于数据库中间件的纯Java驱动程序(类型3):此驱动程序将JDBC调用发送到可以连接到不同类型数据库的中间件服务器。我们应该安装一个中间件服务器来使用这个驱动程序。这增加了额外的网络调用和性能降低,这就是为什么不广泛使用JDBC驱动程序。

直接到数据库的纯Java驱动程序(类型4):此驱动程序将JDBC调用转换为数据库服务器可以理解的网络协议。该解决方案简单,适用于网络上的数据库连接。但是对于此解决方案,我们应该使用特定于数据库的驱动程序,例如Oracle for Oracle DB的OJDBC jar和MySQL Connector的MySQL Connector / J

3JDBC API如何帮助我们实现Java程序和JDBC驱动程序API之间的松散耦合?

JDBC API使用Java Reflection API实现java程序和JDBC驱动程序之间的松散耦合。如果你看一个简单的JDBC例子,你会发现所有的编程都是用JDBC API完成的,而驱动程序只有在通过反射使用ClassforName()方法加载时才会出现。

我认为这是在核心java类中使用Reflection的最佳示例之一,以确保我们的应用程序不能直接使用Drivers API,这使得从一个数据库移动到另一个数据库变得非常容易。

4什么是JDBC连接?解释在简单的java程序中获取数据库连接的步骤。

JDBC Connection就像使用数据库服务器创建的Session。您还可以将Connection 视为来自数据库服务器的Socket连接。

创建JDBC连接非常简单,需要两个步骤:

注册并加载驱动程序:使用ClassforName(),驱动程序类注册到DriverManager并加载到内存中。

使用DriverManager获取Connection对象:我们DriverManagergetConnection()通过传递数据库URL字符串,用户名和密码作为参数来获取连接对象。

Connection

5JDBC DriverManager类有什么用?

JDBC DriverManager是我们通过它获取数据库连接对象的工厂类。当我们加载JDBC Driver类时,它将自己注册到DriverManager,您可以查找JDBC Driver类源代码来检查它。

当我们通过传递数据库配置细节来调用方法DriverManagergetConnection()时,DriverManager使用已注册的驱动程序来获取Connection并将其返回给调用者程序。

6如何在java程序中获取数据库服务器的详细信息?

我们可以使用DatabaseMetaDataobject来获取数据库服务器的详细信息。成功创建数据库连接后,我们可以通过调用getMetaData()方法获取元数据对象。我们可以使用DatabaseMetaData中的方法来获取数据库产品名称,版本和详细的配置信息。

DatabaseMetaData

7什么是JDBC Statement?

JDBC API Statement用于在数据库中执行SQL查询。我们可以通过调用Connection createStatement()方法来创建Statement对象。我们可以使用Statement通过不同的执行方法传递查询来执行静态SQL查询,例如execute(),executeQuery(),executeUpdate()等。

由于查询是在java程序中生成的,如果未正确验证用户输入,则可能导致SQL注入问题,可以在SQL注入示例中找到更多详细信息。

默认情况下,每个Statement对象只能同时打开一个ResultSet对象。因此,如果我们想要使用多个ResultSet对象,则每个对象必须由不同的Statement对象生成。Statement接口中的所有execute()方法都隐式关闭一个statment的当前ResultSet对象(如果存在open对象)。

8execute,executeQuery,executeUpdate有什么区别?

Statement execute(String query)用于执行任何SQL查询,如果结果是ResultSet(如运行Select查询),则返回TRUE。当没有ResultSet对象(如运行Insert或Update查询)时,输出为FALSE。我们可以使用getResultSet()获取ResultSet和getUpdateCount()方法来检索更新计数。

Statement executeQuery(String query)用于执行Select查询并返回ResultSet。即使没有与查询匹配的记录,返回的ResultSet也永远不会为null。执行select查询时,我们应该使用executeQuery方法,这样如果有人试图执行insert / update语句,它将抛出javasqlSQLException,并显示消息“executeQuery方法不能用于更新”。

语句executeUpdate(String query)用于执行不返回任何内容的Insert / Update / Delete(DML)语句或DDL语句。输出为int,等于SQL数据 *** 作语言(DML)语句的行数。对于DDL语句,输出为0。

只有在不确定语句类型时才应使用execute()方法,否则使用executeQuery或executeUpdate方法。

9什么是JDBC PreparedStatement?

JDBC PreparedStatement对象表示预编译的SQL语句。我们可以使用它的setter方法来设置查询的变量。

由于PreparedStatement是预编译的,因此可以使用它多次有效地执行此语句。PreparedStatement是Statement的更好选择,因为它会自动转义特殊字符并避免SQL注入攻击。

10如何在JDBC PreparedStatement中设置NULL值?

我们可以使用PreparedStatement setNull()方法将null变量绑定到参数。例如,setNull方法将index和SQL Types作为参数 pssetNull(10, javasqlTypesINTEGER);。

11Statement中的getGeneratedKeys()方法有什么用?

有时,表可以使用自动生成的键来插入主键的唯一列值。我们可以使用Statement getGeneratedKeys()方法获取此自动生成密钥的值。

12PreparedStatement对Statement有什么好处?

PreparedStatement对Statement的一些好处是:

PreparedStatement帮助我们防止SQL注入攻击,因为它会自动转义特殊字符。

PreparedStatement允许我们使用参数输入执行动态查询。

PreparedStatement比Statement快。当我们重用PreparedStatement或使用它的批处理方法执行多个查询时,它变得更加明显。

PreparedStatement帮助我们使用setter方法编写面向对象的代码,而使用Statement我们必须使用String Concatenation来创建查询。如果要设置多个参数,则使用字符串连接编写查询看起来非常难看并且容易出错。

13PreparedStatement的限制是什么以及如何克服它?

PreparedStatement的一个限制是我们不能直接在IN子句中使用它。将PreparedStatement与IN子句一起使用的一些替代方法是:

执行单一查询 性能非常慢,不推荐使用

使用存储过程 特定于数据库,因此不适用于多个数据库应用程序。

动态创建PreparedStatement查询 良好的方法但失去了缓存的PreparedStatement的好处。

在PreparedStatement查询中使用NULL 当您知道变量输入的最大数量时,这是一种很好的方法,可以通过部分执行来扩展以允许无限制的参数。可以在JDBC PreparedStatement IN子句替代中找到更详细的分析。

14什么是JDBC ResultSet?

JDBC ResultSet就像一个表示数据库结果集的数据表,通常通过执行查询数据库的语句来生成。

ResultSet对象维护指向其当前数据行的游标。最初,光标位于第一行之前。next()方法将光标移动到下一行。如果没有更多行,则next()方法返回false,并且可以在while循环中使用它来迭代结果集。

默认的ResultSet对象不可更新,并且只有一个向前移动的游标。因此,您只能迭代一次,并且只能从第一行到最后一行。可以使用以下语法生成可滚动和/或可更新的ResultSet对象。

Statement stmt = concreateStatement(ResultSetTYPE_SCROLL_INSENSITIVE,

ResultSetCONCUR_UPDATABLE);

当生成它的Statement对象关闭,重新执行或用于从多个结果序列中检索下一个结果时,ResultSet对象将自动关闭。

我们可以使用ResultSet getter方法,列名或索引号从1开始检索列数据。

15ResultSet有哪些不同的类型?

在创建Statement时,我们可以根据用户输入获得不同类型的ResultSet对象。如果您将查看Connection方法,您将看到createStatement()和prepareStatement()方法被重载以提供ResultSet类型和并发作为输入参数。

ResultSet对象有三种类型。

ResultSetTYPEFORWARDONLY:这是默认类型,游标只能在结果集中向前移动。

ResultSetTYPESCROLLINSENSITIVE:游标可以前后移动,结果集对创建结果集后其他人对数据库所做的更改不敏感。

ResultSetTYPESCROLLSENSITIVE:游标可以向前和向后移动,结果集对创建结果集后其他人对数据库所做的更改很敏感。基于并发性,有两种类型的ResultSet对象。

ResultSetCONCURREADONLY:结果集是只读的,这是默认的并发类型。

ResultSetCONCUR_UPDATABLE:我们可以使用ResultSet更新方法来更新行数据。

16Statement中的setFetchSize()和setMaxRows()方法有什么用?

我们可以使用setMaxRows(int i)方法来限制数据库从查询返回的行数。您可以使用SQL查询本身实现相同的功能。例如,在MySQL中,我们可以使用LIMIT子句来设置查询返回的最大行数。

理解fetchSize可能很棘手,因为你应该知道Statement和ResultSet是如何工作的。当我们在数据库中执行查询时,将在数据库缓存中获取并维护结果,并返回ResultSet。ResultSet是具有对数据库中结果的引用的游标。

假设我们有一个返回100行的查询,并且我们将fetchSize设置为10,因此在每次数据库访问时,JDBC驱动程序将只获取10行,因此将有10次访问以获取所有行。如果每行需要大量处理时间并且结果中的行数很大,那么设置最佳fetchSize会很有帮助。

我们可以通过Statement对象设置fetchSize,但可以通过ResultSet对象setFetchSize()方法覆盖它。

17如何使用JDBC API调用存储过程?

存储过程是一组SQL查询,它们在数据库中编译,可以从JDBC API执行。JDBC CallableStatement可用于在数据库中执行存储过程。初始化CallableStatement的语法是;

CallableStatement

//我们需要在调用存储过程之前注册外部参数

stmt

我们需要在执行CallableStatement之前注册OUT参数。

18什么是JDBC批处理,它有什么好处?

有时我们需要为数据库运行类似的批量查询,例如将数据从CSV文件加载到关系数据库表。我们知道我们可以选择使用Statement或PreparedStatement来执行查询。除此之外,JDBC API还提供了批处理功能,通过该功能,我们可以一次性为数据库执行大量查询。

JDBC API支持通过Statement和PreparedStatement addBatch()以及executeBatch()方法进行批处理。

批处理比一次执行一个语句更快,因为数据库调用的数量较少。

19什么是JDBC事务管理?我们为什么需要它?

默认情况下,当我们创建数据库连接时,它以自动提交模式运行。这意味着无论何时执行查询并完成查询,都会自动触发提交。因此,我们触发的每个SQL查询都是一个事务,如果我们运行一些DML或DDL查询,则每个SQL语句完成后,更改都会保存到数据库中。

有时我们希望一组SQL查询成为事务的一部分,以便我们可以在所有查询运行正常时提交它们,如果我们得到任何异常,我们可以选择回滚作为事务的一部分执行的所有查询。

JDBC API提供了一种方法,setAutoCommit(boolean flag)通过该方法我们可以禁用连接的自动提交功能。我们应该仅在需要时禁用自动提交,因为除非我们在连接上调用commit()方法,否则不会提交事务。数据库服务器使用表锁来实现事务管理,这是资源密集型过程。所以我们应该在完成交易后立即提交交易。

20如何回滚JDBC事务?

我们可以使用Connection对象rollback()方法来回滚事务。它将回滚事务所做的所有更改,并释放此Connection对象当前持有的所有数据库锁。

21什么是JDBC Savepoint?如何使用它?

有时,事务可以是多个语句的组,我们希望回滚到事务中的特定点。JDBC Savepoint帮助我们在事务中创建检查点,并且我们可以回滚到该特定检查点。

为事务创建的任何保存点都会自动释放,并在提交事务时或在回滚整个事务时变为无效。将事务滚动回保存点会自动释放并使在相关保存点之后创建的任何其他保存点无效。

22什么是JDBC DataSource?它的好处是什么?

JDBC DataSource是javaxsql包中定义的接口,它比DriverManager更强大,可用于数据库连接。我们可以使用DataSource来创建数据库连接,而Driver实现类可以用来获取连接的实际工作。除了获取数据库连接外,DataSource还提供了一些其他功能,例如:

缓存PreparedStatement以加快处理速度 连接超时设置 记录功能 ResultSet最大大小阈值 使用JNDI支持在servlet容器中连接池 在JDBC DataSource上阅读有关DataSource的更多信息。

23如何在Apache Tomcat Server中使用JDBC DataSource和JNDI实现JDBC连接池?

对于部署在servlet容器中的Web应用程序,创建JDBC连接池非常简单,只需要几个步骤。

在容器配置文件中创建JDBC JNDI资源,通常是serverxml或contextxml。例如

server

在Web应用程序中,使用InitialContext查找在第一步中配置的JNDI资源,然后获取连接。

Context

24什么是Apache DBCP API?

如果您使用DataSource获取数据库连接,通常用于获取连接的代码与特定于驱动程序的DataSource实现紧密耦合。除了选择DataSource实现类之外,大多数代码都是样板代码。

Apache DBCP通过提供DataSource实现来帮助我们摆脱这些问题,DataSource实现充当我们的程序和不同JDBC驱动程序之间的抽象层。Apache DBCP库依赖于Commons Pool库,因此请确保它们都在构建路径中。

25什么是JDBC连接隔离级别?

当我们使用JDBC事务来实现数据完整性时,DBMS使用锁来阻止其他人访问事务所访问的数据。DBMS使用锁来防止脏读,不可重复读和幻像读问题。

DBMS使用JDBC事务隔离级别来使用锁定机制,我们可以通过Connection getTransactionIsolation()方法获取隔离级别信息,并使用setTransactionIsolation()方法设置它。

26什么是JDBC RowSet?RowSet有哪些类型?

JDBC RowSet以更灵活的方式保存表格数据,即ResultSet。所有RowSet对象都是从ResultSet派生的,因此它们具有ResultSet的所有功能以及一些其他功能。RowSet接口在javaxsql包中定义。

RowSet提供的一些附加功能包括:

具有属性的Java Bean及其getter-setter方法。RowSet使用JavaBeans事件模型,它们可以向任何已注册的组件发送通知,用于事件,例如光标移动,更新/插入/删除行以及更改为RowSet内容。

默认情况下,RowSet对象是可滚动和可更新的,因此如果DBMS不支持可滚动或可更新的ResultSet,我们可以使用RowSet来获取这些功能。

RowSet大致分为两种类型:

已连接的RowSet对象 - 这些对象连接到数据库,与ResultSet对象最相似。JDBC API仅提供一个连接的RowSet对象javaxsqlrowsetJdbcRowSet,它的标准实现类是comsunrowsetJdbcRowSetImpl 断开连接的RowSet对象 - 这些RowSet对象不需要连接到数据库,因此它们更轻量级且可序列化。它们适合通过网络发送数据。有四种类型的断开连接的RowSet实现。

CachedRowSet - 它们可以获取连接并执行查询并读取ResultSet数据以填充RowSet数据。我们可以在数据断开连接时 *** 作和更新数据,并重新连接到数据库并写入更改。WebRowSet派生自CachedRowSet - 它们可以读写XML文档。JoinRowSet派生自WebRowSet - 它们可以形成SQL JOIN而无需连接到数据源。从WebRowSet派生的FilteredRowSet - 我们可以应用过滤条件,以便只有选定的数据可见。

27ResultSet和RowSet有什么不同?

RowSet对象派生自ResultSet,因此它们具有ResultSet的所有功能以及一些附加功能。RowSet的一大好处是它们可以断开连接,使其轻量级,并且易于通过网络传输。

是否使用ResultSet或RowSet取决于您的要求,但如果您计划使用ResultSet更长的持续时间,则断开连接的RowSet是释放数据库资源的更好选择。

28常见的JDBC异常有哪些?

一些常见的JDBC异常是:

javasqlSQLException - 这是JDBC异常的基本异常类。javasqlBatchUpdateException - 当Batch *** 作失败时抛出此异常,但它依赖于JDBC驱动程序是否抛出此异常或基本SQLException。javasqlSQLWarning - 用于SQL *** 作中的警告消息。javasqlDataTruncation - 当数据值因超出MaxFieldSize而被意外截断时。

29JDBC中的CLOB和BLOB数据类型是什么?

字符大对象(CLOB)是由具有关联代码页的单字节字符组成的字符串。此数据类型适用于存储面向文本的信息,其中信息量可能超出常规VARCHAR数据类型的限制(上限为32K字节)。

二进制大对象(BLOB)是由字节组成的二进制字符串,没有关联的代码页。此数据类型可以存储大于VARBINARY(32K限制)的二进制数据。此数据类型适用于存储图像,语音,图形和其他类型的业务或特定于应用程序的数据。

30什么是JDBC中的“脏读”?哪个隔离级别可防止脏读?

当我们处理事务时,有可能更新行,同时其他查询可以读取更新的值。这会导致脏读,因为更新后的值不是永久性的,已更新行的事务可以回滚到先前的值,从而导致无效数据。

隔离级别TRANSACTIONREADCOMMITTED,TRANSACTION_REPEATABLEREAD和TRANSACTIONSERIALIZABLE阻止了脏读。

31什么是2阶段提交?

当我们在涉及多个数据库的分布式系统中工作时,我们需要使用2阶段提交协议。2阶段提交协议是分布式系统的原子承诺协议。在第一阶段,事务管理器向所有事务资源发送commit-request。如果所有事务资源都正常,则事务管理器将为所有资源提交事务更改。如果任何事务资源响应为Abort,则事务管理器可以回滚所有事务更改。

32JDBC中有哪些不同类型的锁定?

从广义上讲,有两种类型的锁定机制可以防止数据损坏,因为多个用户使用相同的数据。

乐观锁定 - 使用代码实现此锁定。表中引入了一个额外的列以保持更新计数。当您选择该行时,您也会阅读此列,比如“version”。现在,当您尝试更新/删除行时,将在where子句中传递此“version”。因此,如果在其间执行其他线程的更新,则更新将失败。这是避免数据损坏的好方法,但如果有人错过更新其更新语句中的“version”,则可能容易出错。通过这种锁定方式,更新查询看起来如下所示。

mysql> update emp SET name = ‘David’, version = 5 WHERE id = 10 and version = 4;

悲观锁定 - 将记录从选择锁定到读取,更新和提交阶段。这通常由数据库供应商软件完成,并通过使用SELECT FOR UPDATE查询触发。如果线程处理锁定较长时间,则这种锁定行的方式可能导致性能降低和死锁。

除此之外,一些DBMS系统提供锁定机制来锁定单行,表或数据库。

33你对DDL和DML语句有什么了解?

数据定义语言(DDL)语句用于定义数据库模式。创建,更改,删除,截断,重命名语句属于DDL语句,通常它们不返回任何结果。

数据 *** 作语言(DML)语句用于 *** 纵数据库模式中的数据。选择,插入,更新,删除,调用等是DML语句的示例。

34javautilDate和javasqlDate有什么区别?

javautilDate包含有关日期和时间的信息,而javasqlDate包含仅有关日期的信息,它没有时间信息。因此,如果您必须在数据库中保留时间信息,建议使用Timestamp或DateTime字段。

35如何将图像或原始数据插入数据库?

我们可以使用BLOB将图像或原始二进制数据插入数据库。

36什么是幻像读取以及哪种隔离级别阻止了它?

虚拟读取是指事务多次执行查询并获取不同数据的情况。假设事务正在执行查询以根据条件获取数据,然后另一个事务插入与条件匹配的行。现在,当同一事务再次执行查询时,新行将成为结果集的一部分。这个新行被称为Phantom Row,这种情况称为Phantom Read。

只有使用TRANSACTION_SERIALIZABLE隔离级别才能阻止幻像读取。

37什么是SQL警告?如何在JDBC程序中检索SQL警告?

SQLWarning是SQLException的子类,我们可以通过在Connection,Statement和ResultSet对象上调用getWarnings()方法来检索它。SQL警告不会停止脚本的执行,但会警告用户警告。

38如何使用数据库对象作为IN / OUT调用Oracle存储过程?

如果Oracle存储过程具有作为数据库对象的IN / OUT参数,那么我们需要在程序中创建相同大小的Object数组,然后使用它来创建Oracle STRUCT对象。然后我们可以通过调用setSTRUCT()方法为数据库对象设置此STRUCT对象并使用它。

39我们什么时候得到javasqlSQLException:找不到合适的驱动程序?

当SQL URL字符串格式不正确时,您将得到没有合适的驱动程序发现异常。您可以在使用DriverManager的简单Java应用程序或使用DataSource的JNDI资源中获取此异常。异常堆栈跟踪如下所示。

org

在调试此异常时,只需检查日志中打印的URL,如上面的日志中URL URL是’jdbc:mysql:// localhost:3306 / UserDB,而它应该是jdbc:mysql:// localhost:3306 / UserDB 。

40JDBC有哪些最佳实践?

一些JDBC最佳实践是:

数据库资源很重,因此请确保在完成后立即关闭它。Connection,Statement,ResultSet和所有其他JDBC对象都定义了close()方法来关闭它们。

始终在代码中显式关闭结果集,语句和连接,因为如果您在连接池环境中工作,则可能会将连接返回到池,从而导致打开的结果集和语句对象导致资源泄漏。

关闭finally块中的资源,以确保即使在异常情况下它们也会关闭。

使用批处理进行类似的批量 *** 作。

始终对Statement使用PreparedStatement以避免SQL注入并获得PreparedStatement的预编译和缓存优势。

如果要将批量数据检索到结果集中,则为fetchSize设置最佳值有助于获得良好的性能。

数据库服务器可能不支持所有隔离级别,因此请在假设之前进行检查。

更严格的隔离级别会导致性能降低,因此请确保为数据库连接设置了最佳隔离级别。

如果要在Web应用程序中创建数据库连接,请尝试使用JNDI上下文使用JDBC DataSource资源来重用连接。

当您需要长时间使用ResultSet时,请尝试使用断开连接的RowSet。

//传入你的ResultSet

public static void printRS(ResultSet rs) throws SQLException

{

//检索此 ResultSet 对象的列的编号、类型和属性。

ResultSetMetaData rsmd = rsgetMetaData();

//得到当前的列数

int colCount = rsmdgetColumnCount();

while(rsnext()) { //while控制行数

for(int i = 1; i <= colCount; i++ ) {//for循环控制列数

if(i > 1) {

Systemoutprint(",");

}

//得到当前列的列名

String name = rsmdgetColumnName(i);

//得到当前列的值

String value = rsgetString(i);

Systemoutprint(name + "=" + value);

} Systemoutprintln();

}

}

第一步:如何用POI *** 作Excel

@Test

public void createXls() throws Exception{

//声明一个工作薄

HSSFWorkbook wb = new HSSFWorkbook();

//声明表

HSSFSheet sheet = wbcreateSheet("第一个表");

//声明行

HSSFRow row = sheetcreateRow(7);

//声明列

HSSFCell cel = rowcreateCell(3);

//写入数据

celsetCellValue("你也好");

FileOutputStream fileOut = new FileOutputStream("d:/a/bxls");

wbwrite(fileOut);

fileOutclose();

}

第二步:导出指定数据库的所有表

分析:

1:某个数数据库有多少表,表名是什么?―――DataBaseMetadategetMetadate()getTables(null,null,null,new String[]{Table}); - excel的文件名称。

2:对每一个表进行select *** 作。 - 每一个sheet的名称。

3:分析表结构,rsgetMetadate(); ResultSetMedated

4:多个列,列名是什么- 字段名就是sheet的第一行信息。

5:获取每一行的数据 – 放到sheet第一行以后。

@Test

public void export() throws Exception{

//声明需要导出的数据库

String dbName = "focus";

//声明book

HSSFWorkbook book = new HSSFWorkbook();

//获取Connection,获取db的元数据

Connection con = DataSourceUtilsgetConn();

//声明statemen

Statement st = concreateStatement();

//stexecute("use "+dbName);

DatabaseMetaData dmd = congetMetaData();

//获取数据库有多少表

ResultSet rs = dmdgetTables(dbName,dbName,null,new String[]{"TABLE"});

//获取所有表名 - 就是一个sheet

List<String> tables = new ArrayList<String>();

while(rsnext()){

String tableName = rsgetString("TABLE_NAME");

tablesadd(tableName);

}

for(String tableName:tables){

HSSFSheet sheet = bookcreateSheet(tableName);

//声明sql

String sql = "select from "+dbName+""+tableName;

//查询数据

rs = stexecuteQuery(sql);

//根据查询的结果,分析结果集的元数据

ResultSetMetaData rsmd = rsgetMetaData();

//获取这个查询有多少行

int cols = rsmdgetColumnCount();

//获取所有列名

//创建第一行

HSSFRow row = sheetcreateRow(0);

for(int i=0;i<cols;i++){

String colName = rsmdgetColumnName(i+1);

//创建一个新的列

HSSFCell cell = rowcreateCell(i);

//写入列名

cellsetCellValue(colName);

}

//遍历数据

int index = 1;

while(rsnext()){

row = sheetcreateRow(index++);

//声明列

for(int i=0;i<cols;i++){

String val = rsgetString(i+1);

//声明列

HSSFCell cel = rowcreateCell(i);

//放数据

celsetCellValue(val);

}

}

}

conclose();

bookwrite(new FileOutputStream("d:/a/"+dbName+"xls"));

}

以上就是关于resultset.absolute(1)后用resultset.next()为什么总是取不到第一行数据全部的内容,包括:resultset.absolute(1)后用resultset.next()为什么总是取不到第一行数据、帮帮忙 jsp如何把数据库里的数据生成excel文档、在jdbcapi,statement哪个方法可以用来限制查询返回的记录数等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9758983.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存