使用springJdbc遇到的问题
使用spring jdbc的时候遇到个问题。。我想通过这种方法进行批量插入。。
但是baseDao.update(sql, params);每执行一次就自动提交了。。
我也发现了问题所在。。我所设置的Connection和baseDao.update使用的Connection不是同一个。。
spring不是默认把connection放入ThreadLocal么。。
即一个线程中使用同一个connection..为啥我设置的connection还不是同一个
望前辈指教.
你们怎么用spring做批量插入的?
加事物我也可以实现的。
但是我想用原始的setAutoCommit(false)啊。。
难道spring不支持么 --------------------编程问答-------------------- baseDao代码看看啊? --------------------编程问答-------------------- “我所设置的Connection和baseDao.update使用的Connection不是同一个。。”
你都知道原因,还不知道怎么改?
直接把DataSourceUtils.getConnection(baseDao.getDataSource()) 抽出来放在一个变量里面,然后设置自动提交和批量update时都使用这个变量不就行了 --------------------编程问答--------------------
代码如下:
--------------------编程问答--------------------
package insert;
import java.text.ParseException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component("baseDao")
public class BaseDao {
@Resource
private JdbcTemplate jdbcTemplate;
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
// 查最大数字
public int findMaxNum(String sql) {
return getJdbcTemplate().queryForInt(sql);
}
// 查最大g_id,应用从900000开始,游戏从1000000开始
public int findMaxGid(String sql,int game_type) {
// if(game_type==33){
// sql=sql+" where g_id between 900000 and 999999";
// }else if(game_type==34){
// sql=sql+" where g_id > 999999";
// }
return getJdbcTemplate().queryForInt(sql);
}
public void update(String sql, Object[] params) {
getJdbcTemplate().update(sql, params);
}
public String findMaxNumAsString(String sql) {
return getJdbcTemplate().queryForObject(sql, new Object[] {}, java.lang.String.class);
}
// 查游戏对应的tag_id
// public int findTagId(String tagName) {
// return jdbcT.queryForInt("select t1.tag_id from t_game_tag t1 join t_parameter_app t2 on t1.tag_name=t2.id where t2.name ='" + tagName + "' and t1.tag_id between 1300 and 1315");
// }
public static void main(String[] args) throws ParseException {
System.out.println(new BaseDao().getJdbcTemplate());
System.out.println(new BaseDao().getDataSource());
System.out.println(new BaseDao().getDataSource());
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
/**--------------------编程问答-------------------- if(line=="")屌爆了!! --------------------编程问答-------------------- Dao中,对JdbcTemplate的使用有问题,俺自己写了个样例,LZ参考下呗?
* 一个事务中多次更新数据,合理有效的控制事务。如果一个线程中只更新一次数据,就没必要调用这个方法了
* @param sqlArgs map中的key就是sql语句,map中的value就是参数列表
* 比如:map.put("delete from table where id = ?", new Object[] { 1l });
* @return
*/
public Integer updateMoreData(Map<String, Object[]>... sqlArgs) {
Integer result = 0;
if (null != sqlArgs && sqlArgs.length > 0) {
Connection connection = null;
PreparedStatement prepared = null;
try {
connection = getConnNotCommit();
for (int i = 0; i < sqlArgs.length; i++) {
Map<String, Object[]> map = sqlArgs[i];
Object []arr = map.keySet().toArray();
for (int j = 0; j < arr.length; j++) {
prepared = getPrepared(connection, (String) arr[j], (Object[]) map.get(arr[j]));
log.info((String) arr[j]);
result += prepared.executeUpdate();
}
}
clearCacheList();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
prepared.close();
prepared = null;
connection.commit();
connection.close();
connection = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return result;
}
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* BatchSqlUpdate方式实现数据库批量操作
*/
public class TestJdbcTemplate
{
/**
* 核心sql处理器
*/
private JdbcTemplate jdbcTemplate = null;
/**
* 初始化JdbcTemplate
*/
public TestJdbcTemplate(){
BasicDataSource ds = new BasicDataSource();
ds.setUrl("jdbc.url");//带入真实的jdbc.url
ds.setDriverClassName("jdbc.driver");//带入真实的jdbc.driver驱动
ds.setUsername("jdbc.user");//带入真实的数据库登录名
ds.setPassword("jdbc.pass");//带入真实的数据库登录密码
jdbcTemplate = new JdbcTemplate(ds);
}
/**
* 测试样例
*/
public static void main(String[] args)
{
TestJdbcTemplate testJdbcTemplate = new TestJdbcTemplate();
//初始化10个Bean
List<TestBean> testBeans = new ArrayList<TestBean>(10);
TestBean testBean;
for(int i=0;i<10;i++)
{
testBean = new TestBean();
testBean.setAddress("address"+i);
testBean.setPhone("phone"+i);
testBean.setName("name"+i);
testBean.setRole("role"+i);
testBeans.add(testBean);
}
//sql写死的四个参数(数据库需事先创建一个test表,四个字段均为String)
String sql = "insert into test (address, phone, name, role) values (?, ?, ?, ?)";
int[] updatedRows = testJdbcTemplate.insertNewBeans(sql,testBeans);
for (int row : updatedRows)
{
System.out.println("updatedRows:" + row);
}
}
/**
* 批量操作实现方法
* @param sql
* @param testBeans
* @return
*/
public int[] insertNewBeans(String sql,final List<TestBean> testBeans)
{
return jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter(){
public int getBatchSize() {
return testBeans.size();
}
/**
* 目前sql写死的,如果要更灵活的处理,需要进行改造
*/
public void setValues(PreparedStatement ps, int i) throws SQLException {
TestBean testBean = testBeans.get(i);
ps.setString(1,testBean.getAddress());
ps.setString(2,testBean.getPhone());
ps.setString(3,testBean.getName());
ps.setString(4,testBean.getRole());
}});
}
}
/**
* 数据库test表的实体类Bean
*
*/
class TestBean
{
private String address;
private String phone;
private String name;
private String role;
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address;
}
public String getPhone()
{
return phone;
}
public void setPhone(String phone)
{
this.phone = phone;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getRole()
{
return role;
}
public void setRole(String role)
{
this.role = role;
}
}
另外,推荐一个博文:http://blog.csdn.net/s464036801/article/details/8942411
这里对Spring的数据库操作类,分析的很到位。 --------------------编程问答--------------------
试了下。。插入1w条数据时手动终止控制台。。
数据还是进入数据库了。。
现在还是只能通过加事物方式来解决。。。 --------------------编程问答-------------------- connection未绑定到当前线程中,解决方法:
一、在web.xml文件中加入
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name> flushMode </param-name>
<param-value>AUTO </param-value>
</init-param>
</filter>
二、在spring配置中使用TransactionInterceptor声明事务
这两种方法可以为每个线程绑定一个connection。
这样,你在执行插入操作时,只需要开启事务,设置提交方式即可。
另外,如果使用hibernate+spring,在配置sessionFactory的时候好像可以配置批量处理。
补充:Java , Web 开发