我正在使用“插入或更新”查询,如下所示:
String sql =
"INSERT INTO servlets (path, applicationId, startTime, numOfRequests, totalResponseTime, totalBytes)" +
"VALUES (?, ?, NOW(), 1, ?, ?)" +
"ON DUPLICATE KEY UPDATE numOfRequests = numOfRequests + 1, " +
"totalResponseTime = totalResponseTime + ?, totalBytes = totalBytes + ?";
我正在使用预备语句,并以下列方式填写相关参数:
statement = connection.prepareStatement(sql);
statement.setString(1, i_ServletModel.GetPath());
statement.setInt(2, i_ServletModel.GetApplicationId());
statement.setLong(3, i_RequestStats.GetResponseTime());
statement.setLong(4, i_RequestStats.GetBytes());
statement.setLong(5, i_RequestStats.GetResponseTime());
statement.setLong(6, i_RequestStats.GetBytes());
请注意,参数3与参数5完全相同,参数4与参数6完全相同,因为它们在上面的查询中需要相同的值。
我是否可以在查询或参数填充方法中更改任何内容以避免这种“丑陋”的语法?
答案 0 :(得分:6)
使用局部变量,可以使代码不那么难看且容易出错。但JDBC
它不支持命名参数的缺点仍然存在。同一参数将再有多行。
statement = connection.prepareStatement(sql);
long time = i_RequestStats.GetResponseTime();
long bytes = i_RequestStats.GetBytes();
statement.setString(1, i_ServletModel.GetPath());
statement.setInt(2, i_ServletModel.GetApplicationId());
statement.setLong(3,time);
statement.setLong(4, bytes);
statement.setLong(5, time);
statement.setLong(6, bytes);
答案 1 :(得分:1)
对于面临同样问题的开发人员,我建议你创建一个存储过程或函数,这是一个非常好的做法,因为你将返回一个标量值或列表,但避免在那里放入很多逻辑内容。 如果采用此解决方案,则应使用“可调用语句” 希望这会有所帮助。
答案 2 :(得分:1)
正如其他人已经报道的那样,虽然在技术上不可能使用直接的JDBC来使用带有预处理语句的命名参数Spring确实有一些糖,如果它已经在你的堆栈中,它会更加可口。
以下是在查询中使用相同“命名参数”:personId 两次的示例。在封面下,Spring会将SQL :personId 转换为?,但它会根据需要多次应用相同的值。
@Repository
public class RoleRepositoryImpl implements RoleRepository {
private static final String ROLE_ASSIGNMENT_QUERY = "select T.RoleId from \n" +
"(select RoleId from RoleAssignment where OrganizationId=:orgId and PersonId=:personId\n" +
"union\n" +
"select 'TEXTURA_ADMIN' from Administrator where PersonId=:personId) as T\n" +
"inner join Role R on R.RoleId=T.RoleId\n";
public static class RoleQuery extends MappingSqlQuery<Role> {
public RoleQuery(final DataSource ds) {
super(ds, ROLE_ASSIGNMENT_QUERY);
declareParameter(new SqlParameter("orgId", Types.INTEGER));
declareParameter(new SqlParameter("personId", Types.INTEGER));
compile();
}
@Override
protected Role mapRow(final ResultSet rs, final int rowNum) throws SQLException {
try {
return Role.valueOf(rs.getString(1));
} catch (final IllegalArgumentException ex) {
return null;
}
}
}
}
然后使用示例
private final RoleQuery roleQuery;
public RoleRepositoryImpl(final DataSource dataSource) {
this.roleQuery = new RoleQuery(dataSource);
}
@Override
public List<Role> findRoles(final Long orgId,
final Long userId) {
final List<Role> roles = roleQuery.executeByNamedParam(ImmutableMap.of(
"orgId", orgId,
"personId", userId));
如果你好奇它在幕后做了什么,你可以看到Spring魔法在这种方法中发生:
org.springframework.jdbc.object.SqlQuery #cuteByNamedParam(java.util.Map,java.util.Map)
答案 3 :(得分:0)
你不能改变SQL语法来引用你已经声明的'VALUES'吗?如下所示:
String sql =
"INSERT INTO servlets (path, applicationId, startTime, numOfRequests, totalResponseTime, totalBytes)" +
"VALUES (?, ?, NOW(), 1, ?, ?)" +
"ON DUPLICATE KEY UPDATE numOfRequests = numOfRequests + 1, " +
"totalResponseTime = totalResponseTime + VALUES(5), totalBytes = totalBytes + VALUES(6)";
......这样你只需要添加一次参数。
答案 4 :(得分:0)
不可能。
但您可以在查询中声明一个变量并多次使用相同的变量。请参阅:http://msdn.microsoft.com/en-IN/library/ms188927.aspx for MSSQL