我使用PostgreSQL作为我的数据库和java servlet与PostgreSQL进行通信。我的应用程序要求我从数据库中获取匹配输入文件的数据。所有文件都以bytea列存储在数据库中。这是我的代码:
String checkdb="select * from key where certificate = '"+c+"';";
Statement stcheck=conn.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet newrs=stcheck.executeQuery(checkdb);
newrs.last();
int rowcount=newrs.getRow();
if(rowcount!=0)
throw new ArithmeticException();
其中certificate
是包含bytea数据的列的名称,c
(已上传)是byte[]
形式的证书。所以我在这里检查上传的证书是否已经存在于数据库中。如果它存在,那么我抛出异常。
但问题是多次上传相同的证书是不是抛出异常就好像两个证书不同。
我是否正确比较了字节值。我该怎么做才能纠正这个问题?
的修改
我尝试将证书列设置为主键。但是证书仍会插入到数据库中。怎么会发生这种情况?由于某种原因,内部比较也失败了
的修改
我尝试检索一个ile并将其转换为字符串:
InputStream input13 = retrs.getBinaryStream("certificate");
ByteArrayOutputStream output13 = new ByteArrayOutputStream();
byte buf[]=new byte[1024];
int len;
IOUtils.copy(input13, output13);
input13.close();
byte[] retvalue=output13.toByteArray();
String s1=new String(retvalue);
String s2=new String(c);
System.out.println("in--------------"+s2);
System.out.println("out----------------"+s1);
19:05:43,156 INFO [STDOUT] in-------------------BEGIN CERTIFICATE-----
MIICIjCCAYsCAQMwDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMCYXMxCzAJBgNV
BAgMAmFzMQswCQYDVQQHDAJhczELMAkGA1UECgwCYXMxCzAJBgNVBAsMAmFzMQsw
CQYDVQQDDAJjYTERMA8GCSqGSIb3DQEJARYCYXMwHhcNMTIwNDEwMDY0ODQ3WhcN
MTMwNDEwMDY0ODQ3WjBSMQswCQYDVQQGEwJhczELMAkGA1UECBMCYXMxCzAJBgNV
BAcTAmFzMQswCQYDVQQKEwJhczELMAkGA1UECxMCYXMxDzANBgNVBAMTBmNsaWVu
dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsfJq9TVgTLqz84nuWpDm+dvI
do2HIWoHkmEPNowK4xn1+qWUPCy30aASWI92YMtE6njtQGyZBYij0iTAxldDktqd
bMdpKAONDlSv71rn+fZPuyenbBFYZexybNVsRMFzTD/F/hiPPXT7E1j9CrgIMxVz
ScZeNATh/dPLwuNQ0dsCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDDUyeIWlKaMMkM
8VRGuDJyKFC8miQfmul6zE4+6RTswHKjcUoje2vhTQgV+GBfqx8ai+ziujx8CeyR
eJWcb1G8gg+LMUNDcTOlXTeBG9L2c/gMOEu7BEjtpojSYmFyEvJEQ5Yep44HKZZb
FSPFVNxGiXBhNxtKQdAu6/smQ/eBNg==
-----END CERTIFICATE-----
19:05:43,156 INFO [STDOUT] out----------------[B@17f8b39
我的检索方式是错误的。因为[B@17f8b39
看起来像记忆位置或类似的东西
的应答
正如@jarnbjo所说,必须记住一件事。什么时候在postgressql中使用字节数组,无论是retieving or inserting
只使用setBytes()
。仅使用字节[]的内存位置(java中的哈希码)插入。
答案 0 :(得分:1)
使用PreparedStatement:
PreparedStatement pstat = conn.prepareStatement(
"select * from key where certificate = ?");
pstat.setBytes(1, c);
ResultSet newrs = pstat.executeQuery();
当然,插入数据时也应该这样做。
答案 1 :(得分:1)
显然,根据您看到的结果,您没有正确地进行比较。你需要做一些调试来弄清楚出了什么问题。我建议按照以下几行进行简单的测试:
在找出存在差异的原因方面,你可能会发现在一个简单的测试用例中插入一个简单的字节数组是有帮助的 - 例如一个由单个字节组成的字节数组。
答案 2 :(得分:1)
我建议您生成文件的校验和并存储在db中,并根据校验和而不是文件的字节检查文件内容
table key{
id int,
certificate blob,
checksum varchar(32)
}
使用以下方法生成byte[] buffer
public String getCheckSum(byte[] buffer) {
StringBuilder builder = new StringBuilder();
try {
MessageDigest complete;
complete = MessageDigest.getInstance("MD5");
byte[] rawCheckSum = complete.digest(buffer);
for(byte b: rawCheckSum) {
builder.append(Integer.toString( ( b & 0xff ) + 0x100, 16).substring( 1 ));
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
return builder.toString();
}
最后,
String checkdb="select * from key where checksum = '" + getCheckSum(c) + "';";
修改强>
将字节插入db时,应使用:
String query = "INSERT INTO key (certificate) VALUES (?)";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setBytes(1, c);
而不是
String query = "INSERT INTO key (certificate) VALUES ('" + c + "')";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.execute();