Java JDBC - PreparedStatement executeUpdate()始终返回1

时间:2018-01-23 21:53:02

标签: java sql sql-server jdbc

目前正在研究java中的代码,该代码从位于各种文件夹中的data文件中检索XML,然后将文件本身和检索到的数据上传到SQL-server Database。我不希望将任何重复的XML文件上传到数据库,但由于文件可以使用随机名称即时检查使用每个文件即将上传的Hash,我将文件上传到下表:

XMLFILES

CREATE TABLE [dbo].[XMLFiles](
    [PathID] [int] NOT NULL,
    [FileID] [int] IDENTITY(1,1) NOT NULL,
    [XMLFileName] [nvarchar](100) NULL,
    [FileSize] [int] NULL,
    [FileData] [varbinary](max) NULL,
    [ModDate] [datetime2](7) NULL,
    [FileHash] [nvarchar](100) NULL,
 CONSTRAINT [PK_XMLFiles] PRIMARY KEY CLUSTERED 
(
    [FileID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

我用来上传文件的代码如下:

public int UploadFile

public int UploadFile(String Path,int pathID) throws SQLException, SAXException, IOException {

                 int ID=-1;
                 String hash;
                 int len,rowCount=0;
                 String query;
                 PreparedStatement pstmt;
                    try {
                    File file = new File(Path);
                    hash=XMLRead.getFileChecksum(file);

                    FileInputStream fis = new FileInputStream(file);
                    len = (int) file.length();
                    query = (" IF NOT EXISTS "
                            + " (SELECT 1"
                            + " FROM XMLFiles"
                            + " WHERE FileSize="+len+" AND FileHash='"+hash+"')"
                            + " BEGIN"
                            + " INSERT INTO XMLFiles (PathID,XMLFileName,FileSize,FileData,ModDate,FileHash) "
                            + " VALUES(?,?,?,?,GETDATE(),?)"
                            + " END;");
                    pstmt = Con.prepareStatement(query);
                    pstmt.setInt(1, pathID);
                    pstmt.setString(2, file.getName());
                    pstmt.setInt(3, len);
                    pstmt.setBinaryStream(4, fis, len);
                    pstmt.setString(5, hash);
                    rowCount=pstmt.executeUpdate();
                    System.out.println("ROWS AFFECTED:-"+rowCount);

                    if (rowCount==0){
                            System.out.println("THE FILE: "+file.getName()+"ALREADY EXISTS IN THE SERVER WITH THE NAME: ");
                            System.out.println(GetFilename(hash));
                    }

                   } catch (Exception e) {
                   e.printStackTrace();
                    }



                return rowCount;                              
            }

我用28个文件执行程序,其中4个文件是重复文件,但名称不同,我知道代码工作正常,因为在每次执行结束时只上传了24个唯一文件,问题是即时通讯使用rowCount检查文件是否已上传,以及文件是否因为重复文件而未上传,我也没有将data的{​​{1}}上传到数据库中,像这样(下面的代码是一个片段来说明我正在做的事情):

file

问题是方法int rowCount=UploadFile(Path,pathID); if (rowCount==1){ //UPLOAD DATA } 中的executeUpdate()总是返回UploadFile,即使1中没有受影响的行,这里是否有遗漏?我无法找到我的代码有什么问题,是database我正在做一个返回IF NOT EXISTS的问题吗?

2 个答案:

答案 0 :(得分:0)

可能是当IF块中的SELECT找到现有行时,它会被计算并返回。

如果没有抛出异常,你可以在没有IF NOT EXISTS检查的情况下尝试INSERT,看看是否是这种情况。如果您没有某种类型的密钥阻止它们被插入,您可能会得到重复项,或者如果您有一个阻止插入的密钥,您可能会收到异常。值得测试看看你得到了什么。

如果SELECT返回1,则可能需要将它们拆分为两个语句,如果第一个找到一行,则只需跳过第二个语句的执行。您可以将它们保存在同一个事务中,基本上您的数据库正在执行当前编写的两个语句。这是更多的代码,但是如果你在同一个事务中执行,它对数据库的影响也是一样的。

答案 1 :(得分:0)

SQL语句返回的更新计数仅针对普通DML语句(INSERTUPDATEDELETE)进行了明确定义。

没有为SQL脚本定义。

该值是服务器为脚本选择返回的值。对于MS SQL Server,它可能是语句/脚本末尾的@@ROWCOUNT值:

  

@@ROWCOUNT设置为受影响或读取的行数。

由于您正在执行SELECT语句,因此它会设置@@ROWCOUNT值。如果为零,则执行INSERT语句,该语句将覆盖@@ROWCOUNT值。

假设永远不会有多个具有该大小/哈希的行,您将始终获得1的计数。