最近在做J-Hi融合SpringJDBC时遇到一个棘手的问题,那就是在insert一条记录时如何取回记录主键值的?问题主要让我纠结在对跨数据库SpringJDBC的处理上,大家都知道象SQLServer或MyServer主键的值是以自增的方式,而象Oracle主建的值通过序列生成并通过insert将值直接插入到表中的。为此SpringJDBC提供了两种机制,
1、主键自增的解决方案
当keyHolder获得主键值后,您可以在任何时候通过访问keyHolder对象得到这个主键值,也就是说只要它的生命期存在,这个主键的值就一直不会丢失。
总结:1)、在执行PreparedStatement之前创建自增主键的持有者对象keyHolder
2)、在创建PreparedStatement对象时一定要声明返回主键值,列如con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS)
3)、只要keyHolder的生命期存在,那么主键的值在任何时候与位置你都可以取得到
2、检索数据库序列生成的主键的解决方案
J-Hi的问题与解决方法
因为J-Hi要实现跨数据库跨多个ORM框架因此对于SpringJDBC这两种方案必须要融合到一起,并且在总体设计上还要与其它的ORM框架(目前J-Hi已融合的ORM框架有hibernate、ibatis2、ibatis3)的接口声明相兼容,因此在对SpringJDBC集成的总体设计上我借鉴了hibernate的方言思想,通过方言将SpringJDBC两种方案融合在J-Hi之中以实现对不同类型数据库主键管理的差异性。
从原生的SQL语句上讲Oracle在insert时要插入主键值,而SQLServer恰好相反必须不能插入主键的值,我在设计上就是抓住这一特性,再结合方言,实现了跨数据库的SpringJDBC, dialect.getSelectKey()方法,对应不同的数据库方言,如果是oracle就会生成主键的值,而如果是SQLServer这个方法不会返回任何值,代码如下
Oracle的方言方法:
最后通过
if(obj.getPrimarykey() == null)
BeanUtil.setPropertyValue(obj, "id", keyHolder.getKey().intValue());
Pojo对象是否主键值(如果没有就说明是自增型的如SQLServer,如果有就说明是序列生成的如Oracle),来将其赋值到POJO的属性中.
1、主键自增的解决方案
KeyHolder keyHolder = new GeneratedKeyHolder();
this.getJdbcTemplate().update(new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
PreparedStatement ps=con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
return ps;
}
}, keyHolder);
return keyHolder.getKey().intValue();
keyHolder 是数据库自增主键值的持有者,它监听PreparedStatement的返回的值Statement.RETURN_GENERATED_KEYS获取主键值,并存放在自己的池中(实际上是一个list)一般来说,一个keyHolder实例只绑定一个PreparedStatement的执行,当然最好也只是插入一条数据库记录,这样才能保证池中只有一个主键值。this.getJdbcTemplate().update(new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
PreparedStatement ps=con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
return ps;
}
}, keyHolder);
return keyHolder.getKey().intValue();
当keyHolder获得主键值后,您可以在任何时候通过访问keyHolder对象得到这个主键值,也就是说只要它的生命期存在,这个主键的值就一直不会丢失。
总结:1)、在执行PreparedStatement之前创建自增主键的持有者对象keyHolder
2)、在创建PreparedStatement对象时一定要声明返回主键值,列如con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS)
3)、只要keyHolder的生命期存在,那么主键的值在任何时候与位置你都可以取得到
2、检索数据库序列生成的主键的解决方案
OracleSequenceMaxValueIncrementer incr = new OracleSequenceMaxValueIncrementer(dataSource, "SIMPLE_SEQUENCE");
return incr.nextIntValue();
象Oracle这样的数据库SpringJDBC的解决方案一目了解,通过给定数据源dataSource与序列名"SIMPLE_SEQUENCE"就可以这个序列的最大值。当然还可以通过这个类设计缓冲区大小通过setCacheSize方法,该方法可以一次性取出多个值以减少与数据库的访问次数(数据库的交互是很耗时与耗费资源的)return incr.nextIntValue();
J-Hi的问题与解决方法
因为J-Hi要实现跨数据库跨多个ORM框架因此对于SpringJDBC这两种方案必须要融合到一起,并且在总体设计上还要与其它的ORM框架(目前J-Hi已融合的ORM框架有hibernate、ibatis2、ibatis3)的接口声明相兼容,因此在对SpringJDBC集成的总体设计上我借鉴了hibernate的方言思想,通过方言将SpringJDBC两种方案融合在J-Hi之中以实现对不同类型数据库主键管理的差异性。
KeyHolder keyHolder = new GeneratedKeyHolder();
this.getJdbcTemplate().update(new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
ISpringJDBCHiDialect dialect = sessionFactory.getDialect();
PreparedStatement ps=con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
if(stepFlage == primaryKeyIndex && valueClass.getPropertyName().equals(primaryKeyName)){
Number _id = dialect.getSelectKey(entity.getEntityName(), getJdbcTemplate().getDataSource());
return ps;
}
}, keyHolder);
if(obj.getPrimarykey() == null)
BeanUtil.setPropertyValue(obj, "id", keyHolder.getKey().intValue());
this.getJdbcTemplate().update(new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
ISpringJDBCHiDialect dialect = sessionFactory.getDialect();
PreparedStatement ps=con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
if(stepFlage == primaryKeyIndex && valueClass.getPropertyName().equals(primaryKeyName)){
Number _id = dialect.getSelectKey(entity.getEntityName(), getJdbcTemplate().getDataSource());
return ps;
}
}, keyHolder);
if(obj.getPrimarykey() == null)
BeanUtil.setPropertyValue(obj, "id", keyHolder.getKey().intValue());
从原生的SQL语句上讲Oracle在insert时要插入主键值,而SQLServer恰好相反必须不能插入主键的值,我在设计上就是抓住这一特性,再结合方言,实现了跨数据库的SpringJDBC, dialect.getSelectKey()方法,对应不同的数据库方言,如果是oracle就会生成主键的值,而如果是SQLServer这个方法不会返回任何值,代码如下
Oracle的方言方法:
public Number getSelectKey(String entityName, DataSource dataSource) {
OracleSequenceMaxValueIncrementer incr = new OracleSequenceMaxValueIncrementer(dataSource, "HIBERNATE_SEQUENCE");
return incr.nextIntValue();
}
SQLServer的方言方法:OracleSequenceMaxValueIncrementer incr = new OracleSequenceMaxValueIncrementer(dataSource, "HIBERNATE_SEQUENCE");
return incr.nextIntValue();
}
public Number getSelectKey(String entityName, DataSource dataSource) {
// 自增主键不用实现该方法
return null;
}
通过返回主键值是否为null,还判断在拼写sql时是否插入主键字段的值// 自增主键不用实现该方法
return null;
}
最后通过
if(obj.getPrimarykey() == null)
BeanUtil.setPropertyValue(obj, "id", keyHolder.getKey().intValue());
Pojo对象是否主键值(如果没有就说明是自增型的如SQLServer,如果有就说明是序列生成的如Oracle),来将其赋值到POJO的属性中.
转自:http://www.blogjava.net/hao-zhang-hi/archive/2011/04/21/348599.html
相关推荐
在事务和JDBC操作的配合下,Spring JDBC支持多种数据库供应商,如MySQL、Oracle、PostgreSQL等,这得益于其良好的数据库供应商无关性。通过`DataSource`的配置,开发者可以轻松切换不同的数据库,而无需修改大部分...
Spring Data Redis库提供了对Redis的集成,包括操作键值、哈希、集合、有序集合等功能,并支持事务、发布/订阅模式等高级特性。通过配置RedisTemplate或StringRedisTemplate,可以轻松地在SpringMVC应用中使用Redis...
5. **Spring JDBC**: Spring JDBC模块提供了对JDBC的封装,简化了数据库操作。在整合MySQL时,我们可以通过配置DataSource和JdbcTemplate来执行SQL语句。 6. **整合过程**: - 首先,需要在项目中添加Redis和MySQL...
Mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。在本项目中,Mybatis与MySQL数据库配合,用于数据的增删改查操作,通过XML或注解的方式定义SQL语句。 4. **MySQL**:MySQL是一种关系型数据库管理...
在本项目中,Maven的pom.xml文件定义了所有依赖项,包括Spring、SpringMVC、MyBatis、Redis和MySQL的JDBC驱动,以及所需的其他库。 Spring框架是Java企业级应用的核心组件,提供IoC(Inversion of Control)和AOP...
- 插入(Insert):使用`<insert>`标签定义插入操作,返回主键值。 - 查询(Select):使用`<select>`标签定义查询操作,可选结果映射。 - 更新(Update):使用`<update>`标签定义更新操作。 - 删除(Delete)...
在Spring Boot应用中,我们可以使用JDBC或者JPA(比如Hibernate)来与MySQL进行交互,实现数据的增删改查。 在实际的毕业设计过程中,你可能需要完成以下步骤: 1. **环境搭建**:安装并配置Java环境,下载并设置...
Spring Boot通过JDBC或MyBatis等数据访问技术与MySQL进行交互,实现对数据库的查询和操作。 【Redis】则是一个高性能的键值存储系统,常被用作缓存服务。它以内存中的数据结构存储数据,读写速度快,特别适合频繁...
Mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。Mybatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。在本DEMO...
- **JDBC驱动**:确保项目中包含MySQL的JDBC驱动依赖,如`mysql-connector-java`。 - **数据源配置**:在Spring Boot的配置文件中指定MySQL的连接信息,包括数据库名称、用户名、密码、端口等。 - **自动配置**:...
在Spring Boot中集成MySQL,我们可以使用JDBC或Spring Data JPA来处理数据操作。MyBatis则作为一个优秀的持久层框架,它允许开发者将SQL语句直接写在XML映射文件或注解中,实现了SQL与Java代码的解耦,提高了开发...
jdbc-mysql.url=jdbc:mysql://localhost:3306/test jdbc-mysql.username=root jdbc-mysql.password=229 ``` 这里需要注意,每个数据源的配置都应当独立且完整,包括连接字符串、用户名、密码等必要信息。 #### 3. ...
Spring框架提供了强大的数据访问抽象,包括Spring JDBC模块,使得与数据库交互变得更加简单。本文将深入探讨如何在Java中利用Spring JDBC将数据库查询结果转换为Map对象。 首先,确保已经引入了Spring JDBC的相关...
在本教程中,我们将探讨如何使用Spring Boot、Maven、IntelliJ IDEA和MySQL数据库创建一个实战项目,目的是从数据库获取信息并在前端展示。首先,我们需要确保我们的开发环境已准备就绪,包括安装IntelliJ IDEA作为...
SpringBoot 整合 MySQL 通常使用 `spring-boot-starter-jdbc` 或 `spring-boot-starter-data-jpa` 依赖,其中 JPA(Java Persistence API)是 Java 提供的 ORM(对象关系映射)标准,可以方便地进行对象与数据库表...
MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 ...
Spring Boot通过JDBC或MyBatis等库与MySQL交互,进行数据的CRUD操作。 综上所述,"shiro-freemarker-springBoot-redis-mysql"项目是一个利用JavaWeb技术栈构建的全功能Web应用。它利用Shiro进行安全控制,...
例如,我们可以使用`@Entity`注解来标记一个Java类为数据库实体,`@Table`来指定对应的数据库表,`@Id`来定义主键,以及`@GeneratedValue`来自动生成主键值。 接下来,我们需要配置Spring的ApplicationContext,...
MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 ...
该贷款项目是一个基于Java技术栈的全面解决方案,利用Spring、SpringMVC、Mybatis和Redis等主流框架构建,配合MySQL数据库,旨在实现高效且可扩展的信贷服务。下面将详细介绍这些关键技术及其在项目中的作用。 1. *...