- 浏览: 448747 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
g_man1990:
update config 不成功啊
build-helper-maven-plugin 配置多 source resource 文件 -
netwelfare:
文章很详细,就是太长了,读起来有点困难,倒不如写精练点,像这篇 ...
Java 基本类型 -
huyuancai1010:
function commitForm() {
var ...
加时间戳或者随机数去除js缓存 -
Smile__:
不过这个东西以前还真没研究过 。
hibernate.jdbc.fetch_size 和 hibernate.jdbc.batch_size -
Smile__:
想不到你也是北大青鸟的 。哈
hibernate.jdbc.fetch_size 和 hibernate.jdbc.batch_size
SimpleJdbcInsert
类和SimpleJdbcCall
类主要利用了JDBC驱动所提供的数据库元数据的一些特性来简化数据库操作配置。 这意味着你可以尽可能的简化你的数据库操作配置。当然,你可以可以将元数据处理的特性关闭,从而在你的代码中详细指定这些特性。
让我们从SimpleJdbcInsert
类开始。我们将尽可能使用最少量的配置。SimpleJdbcInsert
类必须在数据访问层的初始化方法中被初始化。 在这个例子中,初始化方法为setDataSource
方法。你无需继承自SimpleJdbcInsert
类,只需要创建一个新的实例,并通过withTableName
方法设置table名称。 这个类使用了“fluid”模式返回SimpleJdbcInsert
,从而你可以访问到所有的可以进行配置的方法。在这个例子中,我们只使用了一个方法,稍后我们会看到更多的配置方法。
public class JdbcActorDao implements ActorDao { private SimpleJdbcTemplate simpleJdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource).withTableName("t_actor"); } public void add(Actor actor) { Map<String, Object> parameters = new HashMap<String, Object>(3); parameters.put("id", actor.getId()); parameters.put("first_name", actor.getFirstName()); parameters.put("last_name", actor.getLastName()); insertActor.execute(parameters); } // ... additional methods }
这个方法通过接收 java.utils.Map
作为它唯一的参数。 在这里需要重点注意的是,在Map中的所有的key,必须和数据库中定义的列名完全匹配。这是因为我们是通过读取元数据来构造实际的Insert语句的。
接下来,我们对于同样的插入语句,我们并不传入id,而是通过数据库自动获取主键的方式来创建新的Actor对象并插入数据库。 当我们创建SimpleJdbcInsert
实例时, 我们不仅需要指定表名,同时我们通过usingGeneratedKeyColumns
方法指定需要数据库自动生成主键的列名。
public class JdbcActorDao implements ActorDao { private SimpleJdbcTemplate simpleJdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("t_actor") .usingGeneratedKeyColumns("id"); } public void add(Actor actor) { Map<String, Object> parameters = new HashMap<String, Object>(2); parameters.put("first_name", actor.getFirstName()); parameters.put("last_name", actor.getLastName()); Number newId = insertActor.executeAndReturnKey(parameters); actor.setId(newId.longValue()); } // ... additional methods }
这样我们可以看到与之前执行的insert操作的不同之处在于,我们无需添加id到参数的Map中去,只需要调用executeReturningKey
方法。 这个方法将返回一个java.lang.Number
对象,我们可以使用这个对象来创建一个字符类型的实例作为我们的域模型的属性。 有一点很重要的地方需要注意,我们无法依赖所有的数据库来返回我们指定的Java类型,因为我们只知道这些对象的基类是java.lang.Number
。 如果你有联合主键或者那些非数字类型的主键需要生成,那么你可以使用executeReturningKeyHolder
方法返回的KeyHolder
对象。
通过指定所使用的字段名称,可以使SimpleJdbcInsert仅使用这些字段作为insert语句所使用的字段。这可以通过usingColumns
方法进行配置。
public class JdbcActorDao implements ActorDao { private SimpleJdbcTemplate simpleJdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("t_actor") .usingColumns("first_name", "last_name") .usingGeneratedKeyColumns("id"); } public void add(Actor actor) { Map<String, Object> parameters = new HashMap<String, Object>(2); parameters.put("first_name", actor.getFirstName()); parameters.put("last_name", actor.getLastName()); Number newId = insertActor.executeAndReturnKey(parameters); actor.setId(newId.longValue()); } // ... additional methods }
执行这样的insert语句所使用的字段,与之前我们所依赖的数据库元数据是一致的。
使用Map来指定参数值有时候工作得非常好,但是这并不是最简单的使用方式。Spring提供了一些其他的SqlParameterSource
实现类来指定参数值。 我们首先可以看看BeanPropertySqlParameterSource
类,这是一个非常简便的指定参数的实现类,只要你有一个符合JavaBean规范的类就行了。它将使用其中的getter方法来获取参数值。 下面是一个例子:
public class JdbcActorDao implements ActorDao { private SimpleJdbcTemplate simpleJdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("t_actor") .usingGeneratedKeyColumns("id"); } public void add(Actor actor) { SqlParameterSource parameters = new BeanPropertySqlParameterSource(actor); Number newId = insertActor.executeAndReturnKey(parameters); actor.setId(newId.longValue()); } // ... additional methods }
另外一个实现类:MapSqlParameterSource
也使用Map来指定参数,但是他另外提供了一个非常简便的addValue
方法,可以被连续调用,来增加参数。
public class JdbcActorDao implements ActorDao { private SimpleJdbcTemplate simpleJdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("t_actor") .usingGeneratedKeyColumns("id"); } public void add(Actor actor) { SqlParameterSource parameters = new MapSqlParameterSource() .addValue("first_name", actor.getFirstName()) .addValue("last_name", actor.getLastName()); Number newId = insertActor.executeAndReturnKey(parameters); actor.setId(newId.longValue()); } // ... additional methods }
正如你看到的,配置是一样的,区别只是切换了不同的提供参数的实现方式来执行调用。
接下来我们把我们的关注点放在使用 SimpleJdbcCall
来进行存储过程的调用上。 设计这个类的目的在于使得调用存储过程尽可能简单。它同样利用的数据库元数据的特性来查找传入的参数和返回值。 这意味着你无需明确声明那些参数。当然,如果你喜欢,可以依然声明这些参数,尤其对于某些参数,你无法直接将他们映射到Java类上,例如ARRAY类型和STRUCT类型的参数。 在我们的第一个示例中,我们可以看到一个简单的存储过程调用,它仅仅返回VARCHAR和DATE类型。 这里,我特地为Actor类增加了一个birthDate的属性,从而可以使得返回值拥有不同的数据类型。 这个存储过程读取actor的主键,并返回first_name,last_name,和birth_date字段作为返回值。 下面是这个存储过程的源码,它可以工作在MySQL数据库上:
CREATE PROCEDURE read_actor ( IN in_id INTEGER, OUT out_first_name VARCHAR(100), OUT out_last_name VARCHAR(100), OUT out_birth_date DATE) BEGIN SELECT first_name, last_name, birth_date INTO out_first_name, out_last_name, out_birth_date FROM t_actor where id = in_id; END;
正如你看到的,这里有四个参数,其中一个是传入的参数“in_id”,表示了Actor的主键,剩下的参数是作为读取数据库表中的数据所返回的返回值。
SimpleJdbcCall
的声明与SimpleJdbcInsert
类似,你无需继承这个类,而只需要在初始化方法中进行初始化。 在这里例子中,我们只需要指定存储过程的名称。
public class JdbcActorDao implements ActorDao { private SimpleJdbcTemplate simpleJdbcTemplate; private SimpleJdbcCall procReadActor; public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); this.procReadActor = new SimpleJdbcCall(dataSource) .withProcedureName("read_actor"); } public Actor readActor(Long id) { SqlParameterSource in = new MapSqlParameterSource() .addValue("in_id", id); Map out = procReadActor.execute(in); Actor actor = new Actor(); actor.setId(id); actor.setFirstName((String) out.get("out_first_name")); actor.setLastName((String) out.get("out_last_name")); actor.setBirthDate((Date) out.get("out_birth_date")); return actor; } // ... additional methods }
通过SimpleJdbcCall执行存储过程需要创建一个SqlParameterSource
的实现类来指定传入的参数。 需要注意的是,传入参数的名称与存储过程中定义的名称必须保持一致。这里,我们无需保持一致,因为我们使用数据库的元数据信息来决定我们需要什么样的数据库对象。 当然,你在源代码中所指定的名称可能和数据库中完全不同,有的数据库会把这些名称全部转化成大写,而有些数据库会把这些名称转化为小写。
execute
方法接收传入的参数,并返回一个Map作为返回值,这个Map包含所有在存储过程中指定的参数名称作为key。 在这个例子中,他们分别是out_first_name,out_last_name
和 out_birth_date
。
execute
方法的最后部分是使用存储过程所返回的值创建一个新的Actor实例。 同样的,这里我们将名称与存储过程中定义的名称保持一致非常重要。在这个例子中,在返回的Map中所定义的key值和数据库的存储过程中定义的值一致。 你可能需要在这里指定Spring使用Jakarta Commons提供的CaseInsensitiveMap
。这样做,你需要在创建你自己的JdbcTemplate
类时,设置setResultsMapCaseInsensitive
属性为True。 然后,你将这个自定义的JdbcTemplate
传入SimpleJdbcCall
的构造函数。当然,你需要把commons-collections.jar
加入到classpath中去。 下面是配置示例:
public class JdbcActorDao implements ActorDao { private SimpleJdbcCall procReadActor; public void setDataSource(DataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); this.procReadActor = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("read_actor"); } // ... additional methods }
通过这样的配置,你就可以无需担心返回参数值的大小写问题。
你已经看到如何通过元数据来简化参数配置,但是你也可以明确地指定这些参数。可以在创建SimpleJdbcCall
时,通过使用declareParameters
方法来声明参数。 这个方法接收一组SqlParameter
对象作为参数。我们可以参照下一个章节,如何创建SqlParameter
。
我们可以有选择性的显示声明一个、多个、甚至所有的参数。参数元数据在这里会被同时使用。 通过调用withoutProcedureColumnMetaDataAccess
方法,我们可以指定数据库忽略所有的元数据处理并使用显示声明的参数。 另外一种情况是,其中的某些参数值具有默认的返回值,我们需要在返回值中指定这些返回值。为了实现这个特性,我们可以使用useInParameterNames
来指定一组需要被包含的参数名称。
这是一个完整的声明存储过程调用的例子:
public class JdbcActorDao implements ActorDao { private SimpleJdbcCall procReadActor; public void setDataSource(DataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); this.procReadActor = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("read_actor") .withoutProcedureColumnMetaDataAccess() .useInParameterNames("in_id") .declareParameters( new SqlParameter("in_id", Types.NUMERIC), new SqlOutParameter("out_first_name", Types.VARCHAR), new SqlOutParameter("out_last_name", Types.VARCHAR), new SqlOutParameter("out_birth_date", Types.DATE) ); } // ... additional methods }
执行和最终的返回处理是相同的,我们在这里只是明确声明了参数类型,而不是依赖数据库元数据特性。 这一点很重要,尤其对于那些数据库并不支持元数据的情况。当前,我们支持元数据的特性的数据包含:Apache Derby、DB2、MySQL、 Microsoft SQL Server、Oracle和Sybase。我们同时对某些数据库内置函数支持元数据特性:MySQL、Microsoft SQL Server和Oracle。
为SimpleJdbc类或者后续章节提到的RDBMS操作指定参数,你需要使用SqlParameter
或者他的子类。 你可以通过指定参数名称以及对应的SQL类型并传入构造函数作为参数来指定SqlParameter
,其中,SQL类型是java.sql.Types
中所定义的常量。 我们已经看到过类似的声明:
new SqlParameter("in_id", Types.NUMERIC), new SqlOutParameter("out_first_name", Types.VARCHAR),
第一行的SqlParameter
定义了一个传入参数。传入参数可以在所有的存储过程中使用,也可以在稍后章节中提到的SqlQuery
类及其子类中使用。
第二行SqlOutParameter
定义了一个返回值。它可以被存储过程调用所使用。当然,还有一个SqlInOutParameter
类,可以用于输入输出参数。 也就是说,它既是一个传入参数,也是一个返回值。
除了参数名称和SQL类型,你还可以声明一些其他额外的选项。对于传入参数,你可以为numeric数据类型指定精度,或者对于特定的数据库指定特殊类型。 对于返回值,你可以提供一个RowMapper
接口来处理所有从REF cursor返回的列。另外一个选项是指定一个SqlReturnType
类,从而可以定制返回值的处理方式。
内置函数的调用几乎和存储过程的调用是一样的。唯一的不同在于,你需要声明的是一个函数的名称而不是存储过程的名称。 这可以通过withFunctionName
方法来完成。使用这个方法,表明你的调用是一个函数。你所指定的这个函数名称将被作为调用对象。 同时有一个叫做executeFunction
的方法,将获得特定的Java类型的函数调用的返回值。 此时,你无需通过返回的Map来获取返回值。另外有一个类似的便捷方法executeObject
用于存储过程,但是他只能处理单个返回值的情况。 下面的示例展示了一个叫做get_actor_name
的函数调用,返回actor的完整的名称。 这个函数将工作在MySQL数据库上。
CREATE FUNCTION get_actor_name (in_id INTEGER) RETURNS VARCHAR(200) READS SQL DATA BEGIN DECLARE out_name VARCHAR(200); SELECT concat(first_name, ' ', last_name) INTO out_name FROM t_actor where id = in_id; RETURN out_name; END;
调用这个函数,我们依然在初始化方法中创建SimpleJdbcCall
public class JdbcActorDao implements ActorDao { private SimpleJdbcTemplate simpleJdbcTemplate; private SimpleJdbcCall funcGetActorName; public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); this.funcGetActorName = new SimpleJdbcCall(jdbcTemplate) .withFunctionName("get_actor_name"); } public String getActorName(Long id) { SqlParameterSource in = new MapSqlParameterSource() .addValue("in_id", id); String name = funcGetActorName.executeFunction(String.class, in); return name; } // ... additional methods }
被调用的函数返回一个String
类型。
期望通过调用存储过程或者函数来返回ResultSet一直是一个问题。一些数据库在JDBC结果处理中返回结果集,而另外一些数据库则需要明确指定返回值的类型。 无论哪种方法,都需要在循环遍历结果集时,做出一些额外的工作,从而处理每一条记录。 通过SimpleJdbcCall
,你可以使用returningResultSet
方法,并定义一个RowMapper
的实现类来处理特定的返回值。 当结果集在返回结果处理过程中没有被定义名称时,返回的结果集必须与定义的RowMapper
的实现类指定的顺序保持一致。 而指定的名字也会被用作返回结果集中的名称。
在这个例子中,我们将使用一个存储过程,它并不接收任何参数,返回t_actor表中的所有的行,下面是MySQL数据库中的存储过程源码:
CREATE PROCEDURE read_all_actors() BEGIN SELECT a.id, a.first_name, a.last_name, a.birth_date FROM t_actor a; END;
要调用这个存储过程,我们需要定义一个RowMapper
的实现类。我们所使用的类遵循JavaBean的规范,所以我们可以使用ParameterizedBeanPropertyRowMapper
作为实现类。 通过将相应的class类作为参数传入到newInstance方法中,我们可以创建这个实现类。
public class JdbcActorDao implements ActorDao { private SimpleJdbcTemplate simpleJdbcTemplate; private SimpleJdbcCall procReadAllActors; public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); this.procReadAllActors = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("read_all_actors") .returningResultSet("actors", ParameterizedBeanPropertyRowMapper.newInstance(Actor.class)); } public List getActorsList() { Map m = procReadAllActors.execute(new HashMap<String, Object>(0)); return (List) m.get("actors"); } // ... additional methods }
这个函数调用传入一个空的Map进入,因为这里不需要任何的参数传入。而函数调用所返回的结果集将返回的是Actors列表。
发表评论
-
Hibernate search
2011-02-21 14:44 3422Hibernate Search是Hibernate的子项目, ... -
Hibernate 注解 annotation
2010-05-05 20:37 15028一、 实体 Bean 每个持久化POJO类都是一个实体Bea ... -
Hibernate 拦截器 和 监听器
2009-11-25 11:29 1876拦截器(Intercept):顾名思义,拦截操作,也就是在Hi ... -
hibernate.jdbc.fetch_size 和 hibernate.jdbc.batch_size
2009-11-17 17:32 19923hibernate.jdbc.fetch_size 50 h ... -
Hibernate 二级缓存 和 查询缓存
2009-09-22 11:19 3067自己测试的一些结果 , ... -
get 会使用二级缓存
2009-09-03 17:17 1449经常看到session.get()和session.load( ... -
Query.list 与 Query.iterate 的区别
2009-09-03 17:08 1942list: 结果存入缓存,但不从缓存里面取;查询时属性连同id ... -
Jdbc 与 Jta 事务
2009-08-26 14:35 2665hibernate的两种事务管理jdbc 和jta方式。下边说 ... -
Hibernate Session Flush
2009-08-14 11:34 8621session flush在commit之前默 ... -
GenericSpringDAO<T extends ...>
2009-08-03 10:06 1519import java.io.Serializable;imp ... -
Hibernate Annotation driven equals and hashCode
2009-07-03 16:56 1471The following implementation of ... -
hibernate cascade inverse
2009-06-28 19:43 1147这两个属性都用于一多 ... -
Hibernate Criteria
2009-06-19 11:15 1064Hibernate 设计了 CriteriaSpec ... -
Hibernate的Criteria 简单用法
2009-05-26 16:52 1801在hibernate的Session里面使用createCri ... -
Hibernate中Criteria的完整用法
2009-05-26 16:46 615Criteria 在查询方法设计上可以灵活的根据 Criter ... -
Hibernate 的连接池属性简介
2009-05-07 11:30 1656Hibernate配置属性 ... -
Hibernate Inverse
2009-04-23 17:15 1277一、Inverse是hibernate双向关系中的基本概念。i ... -
hibernate的hibernate.hbm2ddl.auto属性
2009-01-06 16:33 2370<property name="hibern ... -
hibernate主键常用方式
2009-01-06 16:32 10431) assigned 主键由外部程序负责生成,无需Hibe ...
相关推荐
### 一、Spring Framework与SimpleJDBC简介 **Spring Framework** 是一个开源的应用框架,旨在简化企业级应用程序的开发过程。该框架始于2003年,由Rod Johnson基于其著作《J2EE Design and Development》中的代码...
"simplejdbc_demo"是一个关于Java JDBC(Java Database Connectivity)的基础示例项目,它可能是为了帮助初学者理解如何在Java应用程序中与数据库进行交互。在这个项目中,开发者可能使用了简单的JDBC API来执行常见...
SimpleJdbc-1.0 官方资源!!
Java-SimpleJDBC是一个针对Java开发者的开源项目,旨在简化Java数据库操作,通过提供简洁的API来处理JDBC(Java Database Connectivity)相关的任务。在Java编程中,JDBC是连接和操作关系型数据库的标准接口,它允许...
《深入解析SimpleJDBC:基于开源项目galimatias-0.0.4.zip》 在IT行业中,数据库的访问和操作是不可或缺的一部分。对于Amazon SimpleDB这样轻量级、无模式的云数据库服务,其提供的SimpleJDBC驱动程序为开发者提供...
public class SimpleJDBC { public static void main(String[] args) { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { // 加载 JDBC 驱动 Class.forName(...
测试章节提供了单元测试和集成测试的示例和最佳实践,包括JDBC测试和使用SimpleJdbc类简化JDBC操作的方法。这部分也涵盖了Spring框架下的测试策略,包括DAO和JDBC测试支持。 数据访问章节涵盖了使用Spring JDBC框架...
- **SimpleJdbc类**:介绍了Spring JDBC提供的SimpleJdbc系列类,它们提供了执行简单SQL语句的方法。 - **更新与执行**:讲解了如何使用JdbcTemplate进行数据的更新和执行,包括插入、更新和删除操作。 - **二进制...
示例中的`SimpleJDBC`程序展示了如何通过`Statement`执行查询,并使用`ResultSet`遍历结果集,打印出每条记录的列值。 ### 5. 错误处理 在数据库操作中,错误处理非常重要。给定的部分内容中,通过`try-catch`结构...
DAO支持和JDBC测试支持章节可能讲述了如何在Spring中使用DAO模式,并且使用JDBC进行数据访问,包括Spring JDBC框架的介绍、控制数据库连接、JDBC批量操作和利用SimpleJdbc类简化JDBC操作。 ORM和数据访问章节介绍了...
- JdbcTemplate与SimpleJdbc*系列类的使用方法。 - Spring提供的ORM框架集成支持,包括Hibernate、MyBatis等。 - 事务管理的实现策略与配置方式。 7. **Spring测试框架介绍**: - Spring TestContext Framework...
- **JDBC**:通过Spring的JdbcTemplate或SimpleJdbc*系列类简化JDBC操作。 - **ORM**:整合Hibernate、MyBatis等ORM框架,提供面向对象的数据库操作方式。 - **JPA**:Java Persistence API,提供了一种基于Java的...
Not Using Commons Logging ................................................................... 12 Using SLF4J ..............................................................................................
11.5. 通过使用SimpleJdbc类简化JDBC操作 11.5.1. 使用SimpleJdbcInsert插入数据 11.5.2. 使用SimpleJdbcInsert来获取自动生成的主键 11.5.3. 指定SimpleJdbcInsert所使用的字段 11.5.4. 使用SqlParameterSource...
11.5. 通过使用SimpleJdbc类简化JDBC操作 11.5.1. 使用SimpleJdbcInsert插入数据 11.5.2. 使用SimpleJdbcInsert来获取自动生成的主键 11.5.3. 指定SimpleJdbcInsert所使用的字段 11.5.4. 使用SqlParameterSource...
Not Using Commons Logging ................................................................... 12 Using SLF4J ..............................................................................................
Simple Jdbc 是一个类的集合,用于简化 jdbc 编码,完全没有依赖关系。
telekom_jpa_spring Materialien zum培训: HR-Schema.pdf ---- Datenbank样本架构 JPA_Overview.pdf ----叶面讲义 h2.zip ---- Skripte zum Anlegen des Datenbank...sk.train.x10_SimpleJDBC_Solution ----通过JDBC
#Lesson-SpringJDBC-Demo 它是什么? 我要在培训下,这是一个简短的项目,用于教授新一批学生,Spring Demo! 它包含什么 项目中的每个分支代表下一组分配。 如果学生在完成任务时...simpleJdbc.driver com.mysql