深刻淺出JDBC(四) - Insert與Spring SimpleJdbcInsert

Sql的Insert操做,由於表的主鍵通常都設置成自增的緣由,相較於update操做,多了對自增id的獲取。spring jdbc對insert操做的支持也很完善,不只在JdbcTemplate的update方法中支持返回主鍵,更是單獨提供SimpleJdbcInsert類幫助使用insert操做。java

JdbcTemplate的Insert

spring使用KeyHolder做爲自增列返回的持有器,update方法支持PreparedStatementCreator和KeyHolder兩個參數,來完成insert操做並返回自增列的值。mysql

@Test
public void testInsertAutoGeneratedKey(){
	final String insertSql = "insert into t_wms_goods_stock (warehouse_id, amount) values(?,?)";
	
	// 建立自增key的持有器
	KeyHolder keyHolder = new GeneratedKeyHolder();
	int insertRow = jdbcTemplate.update(new PreparedStatementCreator() {
		
		public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
			// 獲取PreparedStatement,並指定返回自增key
			PreparedStatement ps = con.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
			ps.setLong(1, 1L);
			ps.setDouble(2, 100.25);
			return ps;
		}
	}, keyHolder);
	
	if(insertRow > 0){
		// getKey返回單一自增值
		System.out.println("auto-generated key:" + keyHolder.getKey());
	}
}

KeyHolder的getKey方法返回的是Number類型spring

若是是批量insert,也能夠支持sql

@Test
public void testMultiInsertAutoGeneratedKey(){
	final String insertSql = "insert into t_wms_goods_stock (warehouse_id, amount) values(?,?),(?,?)";
	
	KeyHolder keyHolder = new GeneratedKeyHolder();
	int insertRow = jdbcTemplate.update(new PreparedStatementCreator() {
		
		public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
			PreparedStatement ps = con.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
			ps.setLong(1, 1L);
			ps.setDouble(2, 100.25);
			ps.setLong(3, 2L);
			ps.setDouble(4, 122.9);
			return ps;
		}
	}, keyHolder);
	
	if(insertRow > 0){
		// getKeyList返回批量自增值
		System.out.println("auto-generated key:" + keyHolder.getKeyList());
	}
}

可是返回的是List<Map<String, Object>>,map的key是ColumnKey,value就是自增列的值。筆者使用的是mysql,返回的數據以下:數據庫

[{GENERATED_KEY=17}, {GENERATED_KEY=18}]

因爲mysql一張表裏不容許設置兩個自增列,是否返回的自增column key名稱就是GENERATED_KEY,筆者不能確認,若是有明確知曉的朋友,還請告知。api

SimpleJdbcInsert

爲了簡化insert操做,spring提供了一個簡便的,基於流式api的支持表插入的類,就是SimpleJdbcInsert。SimpleJdbcInsert提供三個execute方法執行insert操做3d

// 普通insert,返回影響行數
public int execute(Map<String, ?> args) {
	return doExecute(args);
}

// 有自增id的單條insert
public Number executeAndReturnKey(Map<String, ?> args) {
	return doExecuteAndReturnKey(args);
}

// 有自增id的insert,返回KeyHolder
public KeyHolder executeAndReturnKeyHolder(Map<String, ?> args) {
	return doExecuteAndReturnKeyHolder(args);
}

先來看普通的insertcode

@Test
public void testInsertWithMap(){
	SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate)
			.withTableName("t_wms_goods_stock");
	
	Map<String, Object> params = new HashMap<>();
	params.put("id", 3);
	params.put("warehouse_id", 1);
	params.put("amount", 15d);
	int insertCount = insert.execute(params);
	System.out.println("insertCount:" + insertCount);
}

傳入JdbcTemplate構造SimpleJdbcInsert,而後賦予操做的表名,使用map構造insert的column name和對應的column value,調用execute執行,返回影響的行數。簡單深刻下源碼,能夠看到底層執行的仍是JdbcTemplate的方法。對象

getJdbcTemplate().update(getInsertString(), values.toArray(), getInsertTypes());

再來看有主鍵遞增的insertget

@Test
public void testInsertWithMapAndGeneratedKey(){
	SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate)
			.withTableName("t_wms_goods_stock")
			// 設置自增column
			.usingGeneratedKeyColumns("id");
	
	Map<String, Object> params = new HashMap<>();
	params.put("warehouse_id", 1);
	params.put("amount", 32d);
	Number newId = insert.executeAndReturnKey(params);
	System.out.println("insert new id:" + newId);
}

構造SimpleJdbcInsert時,設置了自增column,而後調用executeAndReturnKey方法,返回Number類型的自增列的值。

對於executeAndReturnKeyHolder方法,因爲參數是map方式,並不能支持批量insert。

至於execute的參數,spring還提供除map外的其餘方式:SqlParameterSource,並提供兩種經常使用的實現。

MapSqlParameterSource

相似於Map的一種參數

@Test
public void testMapSqlParameterSource(){
	SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate)
			.withTableName("t_wms_goods_stock")
			.usingGeneratedKeyColumns("id");
	
	SqlParameterSource parameterSource = new MapSqlParameterSource()
			.addValue("warehouse_id", 1l)
			.addValue("amount", 23d);
	Number newId = insert.executeAndReturnKey(parameterSource);
	System.out.println("insert new id:" + newId);
}

BeanPropertySqlParameterSource

傳入對於的java對象,映射對象屬性名稱到數據庫表的列名稱(將java的駝峯式名稱轉換成sql的下劃線分隔的名稱)

public void testBeanPropertySqlParameterSource(){
	SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate)
			.withTableName("t_wms_goods_stock")
			.usingGeneratedKeyColumns("id");
	
	SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(new GoodsStock(1l, 23d));
	Number newId = insert.executeAndReturnKey(parameterSource);
	System.out.println("insert new id:" + newId);
}

此種方式,對於對象屬性和表字段名稱一致的是很是方便的。

相關文章
相關標籤/搜索