我正在使用simpleJdbcTemplate将数据放入数据库。
simpleJdbcTemplate.update("insert into TABLE values(default)");
我不想放任何数据,因为我不需要它用于我的单元测试目的。
如何从插入的行中获取id?我可以检索当前的序列值但是如果其他人会进行插入,那么我将获得下一个序列值。
有没有办法使用simpleJdbcTemplate插入行并获取id?更新方法返回插入的行数,我想拥有id。谢谢你的帮助。
答案 0 :(得分:5)
你找到答案了吗?如果没有,请尝试使用SimpleJdbcInsert
。
例如:
SimpleJdbcInsert sji = new SimpleJdbcInsert(dataSource)
.withTableName(TableName)
.usingColumns(new String[]{your columns})
.usingGeneratedKeyColumns(you auto-increment id colums);
然后检索
sji.executeAndReturnKey(args).longValue();
答案 1 :(得分:4)
您需要手动处理序列以轻松获取ID,而无需将自己绑定到任何特定的RDBMS产品中。
这意味着您必须指定特定于部署的DataFieldMaxValueIncrementer
bean,并将其注入数据库处理类,就像您最常使用DataSource
一样。 bean定义应该类似于(此示例适用于PostgreSQL):
<bean id="incrementer" class="org.springframework.jdbc.support.incrementer.PostgreSQLSequenceMaxValueIncrementer">
<property name="dataSource" ref="dataSource" />
<property name="incrementerName" value="seq_name" />
</bean>
然后当你的班级中有增量器时,你可以在你的代码中使用它来获得id值,如下所示:
public long saveBeanAndReturnId(Bean b) {
long id = incrementer.nextLongValue();
simpleJdbc.update("...");
return id;
}
答案 2 :(得分:3)
我认为它看起来很艰难......: - O
你不尝试这样的事情:
int newID = simpleJdbcTemplate.queryForInt("INSERT INTO TABLE(Column_Names)
values (default)
RETURNING ID");
现在 newID 将包含新插入的行ID。
CHEERS .. !! :)
答案 3 :(得分:2)
使用NamedParameterJdbcTemplate您有一个keyholder。它抽象了DBMS密钥生成。 检查创建方法。
package info.pello.spring.persistence;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
/**
* DAO for customer entity
* @author Pello Xabier Altadill Izura
* @greetz Blue Mug
*
*/
public class CustomerDAO {
// I use both jdbcTemplate/namedParameterJdbcTemplate depending on needs
private JdbcTemplate jdbcTemplate;
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private final static String CREATE_SQL = "insert into customer (name,address,email) values(:name,:address,:email)";
/**
* gets Customer data from DataBase
* @param customerId
* @return
*/
public Customer read (int customerId) {
Customer customer = null;
return customer;
}
/**
* gets all Customer data from DataBase
* @return list of customers
*/
public List<Customer> readAll () {
List<Customer> customerList = new ArrayList<Customer>();
return customerList;
}
/**
* creates new Customer
* @param newCustomer
* @return
*/
public int create (Customer newCustomer) {
GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
namedParameters.addValue("name", newCustomer.getName());
namedParameters.addValue("address", newCustomer.getAddress());
namedParameters.addValue("email", newCustomer.getEmail());
namedParameterJdbcTemplate.update(CREATE_SQL,
namedParameters,
generatedKeyHolder);
newCustomer.setId(generatedKeyHolder.getKey().intValue());
return newCustomer.getId();
}
/**
* updates customer information
* @param customer
* @return
*/
public int update (Customer customer) {
int result = 0;
return result;
}
/**
* delete customer
* @param customerId
* @return
*/
public int delete (int customerId) {
int result = 0;
return result;
}
/**
* @return the jdbcTemplate
*/
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
/**
* @param jdbcTemplate the jdbcTemplate to set
*/
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* @return the namedParameterJdbcTemplate
*/
public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
return namedParameterJdbcTemplate;
}
/**
* @param namedParameterJdbcTemplate the namedParameterJdbcTemplate to set
*/
public void setNamedParameterJdbcTemplate(
NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
}
}
答案 4 :(得分:1)
您应首先从相应的id
查询sequence
,然后在插入语句中提供id
。就这么简单。
此外,我们称之为集成测试,而不是单元测试。您可能希望参考this SO thread来了解有关集成测试和ID的信息。
[评论后编辑]
在这种情况下,摆脱那个触发器。在制作id
之前,直接从sequence
检索insert
。
好吧,您可以在桌面上触发SELECT... FOR UPDATE
,然后抓住最后一个id
,并将其递增1.如果您的id
不是连续的,我猜不会在这种情况下,您可以保留特定于Oracle AFAIK的ROWID
。然后使用它查询id
。事实上,它的各种解决方法。
注意: 我强烈建议您查看Aaron Digulla的帖子。看看是否足够。
答案 5 :(得分:1)
回答这个问题:你想通过考试达到什么目的?检查更新是否正常运行?你每次都得到一个新的身份证?表存在吗?
根据答案,您必须修改测试。如果您只是想知道语句的语法是正确的,那么除了运行语句之外,您不需要做任何事情(如果测试失败,则会抛出异常)。
如果您想确保每次都获得一个新ID,您必须查询序列两次,并检查第二个值是否与第一个不同。
如果要检查是否插入了具有新唯一ID的行,只需运行插入并检查它是否返回1.如果它有效,您将知道主键(ID)未被违反并插入了一行。因此,“使用唯一ID添加”机制必须有效。
[编辑]无法测试将ID添加到新行的触发器,因为Oracle无法返回刚刚创建的ID。您可以阅读序列,但无法保证nextval-1
会为您提供与触发器相同的结果。
您可以尝试select max(ID)
但如果其他人在您运行查询之前插入另一行并提交它(使用默认事务级别READ_COMMITTED
),则可能会失败。
因此,我强烈建议摆脱触发器并使用其他人使用的标准2步(“获取新ID”加上“使用新ID插入”)算法。它将使您的测试更简单,更脆弱。
答案 6 :(得分:1)
不推荐使用simpleJdbcTemplate,而选择NamedParameterJdbcTemplate。
Pello X有正确答案,但他的提交过于繁琐,无法理解。 简化为:
如果你有一个名为SAMPLE的非常简单的表,其中一个名为NAME的列和一个名为bigint的ID生成的主键:
MapSqlParameterSource namedParameters = new MapSqlParameterSource().addValue("name", name);
KeyHolder keyHolder = new GeneratedKeyHolder();
int numberOfAffectedRows = namedParameterJdbcTemplate.update("insert into SAMPLE(name) values(:name)", namedParameters, keyHolder);
return numberOfAffectedRows == 1 ? keyHolder.getKey().longValue() : -1L;
这将返回更新中唯一生成的密钥,如果受影响的行超过1,则返回-1。
请注意,由于只生成了1个密钥,因此我不关心列名称。
如果生成的密钥超过1个,请查看http://docs.spring.io/spring/docs/3.2.7.RELEASE/javadoc-api/org/springframework/jdbc/support/KeyHolder.html#getKeys%28%29
答案 7 :(得分:0)
使用Spring的JdbcTemplate
,您可以将其update
方法与PreparedStatementCreator
和GeneratedKeyholder
结合使用,以保存新插入的行的主键。
public class SomeDao(){
@Autowired
private JdbcTemplate jdbcTemplate;
//example of a insertion returning the primary key
public long save(final String name){
final KeyHolder holder = new GeneratedKeyHolder();//the newly generated key will be contained in this Object
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(final Connection connection) throws SQLException {
final PreparedStatement ps = connection.prepareStatement("INSERT INTO `names` (`name`) VALUES (?)",
Statement.RETURN_GENERATED_KEYS);
ps.setString(1, name);
return ps;
}
}, holder);
return holder.getKey().longValue();//the primary key of the newly inserted row
}
}