本人博客已搬家,新地址为:http://yidao620c.github.io/
在xml中配置jdbcTemplate:
<context:component-scan base-package="com.springzoo"/>
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"/>
下面是DAO的示例:
@Repository
public class ForumDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public void initDb() {
String sql = "create table t_user(user_id int primary key,user_name varchar(60))";
jdbcTemplate.execute(sql);
}
/**
* 更新一条数据
*
* @param forum
*/
public void addForum(final Forum forum) {
final String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
Object[] params = new Object[] { forum.getForumName(),
forum.getForumDesc() };
// 方式1
// jdbcTemplate.update(sql, params);
// 方式2
// jdbcTemplate.update(sql, params,new
// int[]{Types.VARCHAR,Types.VARCHAR});
// 方式3
/*
* jdbcTemplate.update(sql, new PreparedStatementSetter() { public void
* setValues(PreparedStatement ps) throws SQLException { ps.setString(1,
* forum.getForumName()); ps.setString(2, forum.getForumDesc()); } });
*/
// 方式4
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, forum.getForumName());
ps.setString(2, forum.getForumDesc());
return ps;
}
}, keyHolder);
forum.setForumId(keyHolder.getKey().intValue());
}
public void addForumByNamedParams(final Forum forum) {
final String sql = "INSERT INTO t_forum(forum_name, forum_desc) VALUES(:forumName,:forumDesc)";
SqlParameterSource sps = new BeanPropertySqlParameterSource(forum);
namedParameterJdbcTemplate.update(sql, sps);
}
/**
* 批量更新数据
*
* @param forums
*/
public void addForums(final List<Forum> forums) {
final String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
public int getBatchSize() {
return forums.size();
}
public void setValues(PreparedStatement ps, int index)
throws SQLException {
Forum forum = forums.get(index);
ps.setString(1, forum.getForumName());
ps.setString(2, forum.getForumDesc());
}
});
}
/**
* 根据ID获取Forum对象
*
* @param forumId
* @return
*/
public Forum getForum(final int forumId) {
String sql = "SELECT forum_name,forum_desc FROM t_forum WHERE forum_id=?";
final Forum forum = new Forum();
jdbcTemplate.query(sql, new Object[] { forumId },
new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
forum.setForumId(forumId);
forum.setForumName(rs.getString("forum_name"));
forum.setForumDesc(rs.getString("forum_desc"));
}
});
return forum;
}
public List<Forum> getForums(final int fromId, final int toId) {
String sql = "SELECT forum_id,forum_name,forum_desc FROM t_forum WHERE forum_id between ? and ?";
// 方法1:使用RowCallbackHandler接口
/*
* final List<Forum> forums = new ArrayList<Forum>();
* jdbcTemplate.query(sql,new Object[]{fromId,toId},new
* RowCallbackHandler(){ public void processRow(ResultSet rs) throws
* SQLException { Forum forum = new Forum();
* forum.setForumId(rs.getInt("forum_id"));
* forum.setForumName(rs.getString("forum_name"));
* forum.setForumDesc(rs.getString("forum_desc")); forums.add(forum);
* }}); return forums;
*/
return jdbcTemplate.query(sql, new Object[] { fromId, toId },
new RowMapper<Forum>() {
public Forum mapRow(ResultSet rs, int index)
throws SQLException {
Forum forum = new Forum();
forum.setForumId(rs.getInt("forum_id"));
forum.setForumName(rs.getString("forum_name"));
forum.setForumDesc(rs.getString("forum_desc"));
return forum;
}
});
}
int getForumNum() {
return 0;
}
}
返回数据库的自增主键方法:
Statement stmt = conn.createStatement();
String sql = "INSERT INTO t_topic(....) values(...)";
stmt.executeUpate(sql, Statement.RETURN_GENERATED_KYES);
ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()) {
int key = rs.getInt();
}
spring利用这一技术,提供了一个可以返回新增记录主键的方法,就是上面的方式4:
// 方式4
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, forum.getForumName());
ps.setString(2, forum.getForumDesc());
return ps;
}
}, keyHolder);
forum.setForumId(keyHolder.getKey().intValue());
不过要注意的是,采用数据库的自增主键是不安全的,可以通过查询sequence或者在应用程序中提供主键两种方式保证安全性。
从功能上讲,RowCallbackHandler和RowMapper<T>没有太大区别,在返回多行时候RowMapper<T>更适合,因为不需要手动去往List里面添加。spring宣称RowCallbackHandler接口实现类可以使有状态的,如果它有状态我们就不能在多个地方重用。而RowMapper<T>实现类是没有状态的。
但是注意:如果处理大结果集的时候,使用RowMapper可能会内存泄露,最好使用RowCallbackHandler的实现类RowCountCallbackHandler,在processRow方法中处理结果集数据。一句话,RowMapper是将所有结果返回到一个List中,再去处理。而RowCallbackHandler是一行一行的去处理。
单值查询:
@Repository
public class TopicDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public double getReplyRate(int userId) {
String sql = "SELECT topic_replies,topic_views FROM t_topic WHERE user_id=?";
double rate = jdbcTemplate.queryForObject(sql, new Object[] { userId },
new RowMapper<Double>() {
public Double mapRow(ResultSet rs, int index)
throws SQLException {
int replies = rs.getInt("topic_replies");
int views = rs.getInt("topic_views");
if (views > 0)
return new Double((double) replies / views);
else
return new Double(0.0);
}
});
return rate;
};
public int getUserTopicNum(final int userId) {
String sql = "{call P_GET_TOPIC_NUM(?,?)}";
//方式1
/* Integer num = jdbcTemplate.execute(sql,
new CallableStatementCallback<Integer>() {
public Integer doInCallableStatement(CallableStatement cs)
throws SQLException, DataAccessException {
cs.setInt(1, userId);
cs.registerOutParameter(2, Types.INTEGER);
cs.execute();
return cs.getInt(2);
}
});
return num;*/
//方式2
CallableStatementCreatorFactory fac = new CallableStatementCreatorFactory(sql);
fac.addParameter(new SqlParameter("userId",Types.INTEGER));
fac.addParameter(new SqlOutParameter("topicNum",Types.INTEGER));
Map<String,Integer> paramsMap = new HashMap<String,Integer>();
paramsMap.put("userId",userId);
CallableStatementCreator csc = fac.newCallableStatementCreator (paramsMap);
Integer num = jdbcTemplate.execute(csc,new CallableStatementCallback<Integer>(){
public Integer doInCallableStatement(CallableStatement cs)
throws SQLException, DataAccessException {
cs.execute();
return cs.getInt(2);
}
});
return num;
}
public int getUserTopicNum2(int userId) {
return 0;
};
public SqlRowSet getTopicRowSet(int userId) {
String sql = "SELECT topic_id,topic_title FROM t_topic WHERE user_id=?";
return jdbcTemplate.queryForRowSet(sql,userId);
};
}
处理BLOB/COLB的大数据:
spring定义了一个独立于java.sql.Blob/Clob接口,以统一方式操作各种数据库Lob类型的LobCreator接口。为了方便在PreparedStatement中使用LobCreator,可以直接使用JDBCTemplate#execute(String sql, AbstractLobCreatingPreparedStatementCallback lcpsc)方法。用来set大字段的值
LobHandler接口为操作大二进制字段和大文本字段提供了统一访问接口,不管底层数据库究竟以大对象还是以一般数据类型方式进行操作,此外,LobHandler还充当LobCreator的工厂类。一般使用DefaultLobHandler即可。用来get返回的大字段的值
xml配置,注意lazy-init要设置成true,因为nativeJdbcExtractor需要通过运行时反射机制获取底层JDBC对象:
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource"/> <bean id="nativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" lazy-init="true" /> <bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" lazy-init="true" />
DAO中的用法,往数据库中插入或更新大数据操作:
@Repository
public class PostDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private LobHandler lobHandler;
public void addPost(final Post post){
String sql = " INSERT INTO t_post(post_id,user_id,post_text,post_attach)"
+ " VALUES(?,?,?,?)";
jdbcTemplate.execute(sql,new AbstractLobCreatingPreparedStatementCallback(this.lobHandler) {
protected void setValues(PreparedStatement ps,LobCreator lobCreator)
throws SQLException {
//1:固定主键
ps.setInt(1,1);
ps.setInt(2, post.getUserId());
lobCreator.setClobAsString(ps, 3, post.getPostText());
lobCreator.setBlobAsBytes(ps, 4, post.getPostAttach());
}
});
}
.....
}
以块数据方式读取数据库中大数据:
public List<Post> getAttachs(final int userId) {
String sql = " SELECT post_id,post_attach FROM t_post where user_id =? and post_attach is not null ";
return jdbcTemplate.query(sql, new Object[] { userId },
new RowMapper<Post>() {
public Post mapRow(ResultSet rs, int rowNum)
throws SQLException {
int postId = rs.getInt(1);
byte[] attach = lobHandler.getBlobAsBytes(rs, 2);
Post post = new Post();
post.setPostId(postId);
post.setPostAttach(attach);
return post;
}
});
}
以流数据方式读取Lob数据:
对于体积很大的Lob数据,比如超过50M,我们可以使用流的方式进行访问,减少内存占用。
public void getAttach(final int postId, final OutputStream os) {
String sql = "SELECT post_attach FROM t_post WHERE post_id=? ";
jdbcTemplate.query(sql, new Object[] {postId},
new AbstractLobStreamingResultSetExtractor() {
protected void handleNoRowFound() throws LobRetrievalFailureException {
System.out.println("Not Found result!");
}
public void streamData(ResultSet rs) throws SQLException,IOException {
InputStream is = lobHandler.getBlobAsBinaryStream(rs, 1);
if (is != null) {
FileCopyUtils.copy(is, os);
}
}
}
);
}
自增键和行集RowSet:
之前说过依靠数据库提供的自增键功能,比如mysql的auto_increment是不安全的。spring允许用户在应用层产生主键值,为此定义了org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer接口,提供两种产生主键的方案:一个是通过序列sequence产生,另一个是通过表产生主键。
* AbstractDataFieldMaxValueIncrementer:使用sequence或者模拟序列表产生主键,被下面两个类继承。
* AbstractSequenceMaxValueIncrementer使用标准的sequence产生主键
* AbstractColumnMaxValueIncrementer使用模拟序列表产生主键,可以指定cacheSize一次性缓冲多少个主键值,减少数据库访问次数。
首先在DAO中加入这一行:
@Autowired
private DataFieldMaxValueIncrementer incre;
然后再xml中定义:
<!-- 1:基于数据库序列的自增器 -->
<!--
<bean id="incre"
class="org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer"
p:incrementerName="seq_post_id"
p:dataSource-ref="dataSource"/>
-->
<!-- 1:基于数据表的自增器 -->
<bean id="incre"
class="org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer"
p:incrementerName="t_post_id"
p:columnName="sequence_id"
p:cacheSize="10"
p:dataSource-ref="dataSource"/>
用法:
public void addPost(final Post post){
String sql = " INSERT INTO t_post(post_id,user_id,post_text,post_attach)"
+ " VALUES(?,?,?,?)";
jdbcTemplate.execute(sql,new AbstractLobCreatingPreparedStatementCallback(this.lobHandler) {
protected void setValues(PreparedStatement ps,LobCreator lobCreator)
throws SQLException {
//2:通过自增键指定主键值
ps.setInt(1, incre.nextIntValue());
ps.setInt(2, post.getUserId());
lobCreator.setClobAsString(ps, 3, post.getPostText());
lobCreator.setBlobAsBytes(ps, 4, post.getPostAttach());
}
});
}
规划主键方案:
所有主键全部采用应用层主键产生方案,使用UUID或者DataFieldMaxValueIncrementer生产主键。
以行集返回数据:
RowSet会一次性装载所有的匹配数据,同时会断开数据库的连接。而不是像ResultSet那样,分批次返回一批数据,一批的行数为fetchSize。所以,对于大结果集的数据,使用SqlRowSet会造成很大的内存消耗。
其他的JDBCTemplate:
NamedParameterJDBCTemplate:提供命名参数绑定功能
SimpleJDBCTemplate:将常用的API开放出来
先看一下xml配置文件:
<bean id="namedParamJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
用法如下:
public void addForumByNamedParams(final Forum forum) { final String sql = "INSERT INTO t_forum(forum_name, forum_desc) VALUES(:forumName,:forumDesc)"; // SqlParameterSource sps = new BeanPropertySqlParameterSource(forum); MapSqlParameterSource sps = new MapSqlParameterSource(). addValue("forumName", forum.getForumName()). addValue("forumDesc", forum.getForumDesc()); namedParameterJdbcTemplate.update(sql, sps); }
相关推荐
私信博主免费获取真题解析以及代码
Screenshot_2024-05-10-20-21-01-857_com.chaoxing.mobile.jpg
数字图像处理|Matlab-频域增强实验-彩色图像的频域滤波.zip
2024-2030中国定向转向膜市场现状研究分析与发展前景预测报告
开源工时填报管理系统安装包
电子元件 电子行业 行业分析 数据分析 数据报告 行业报告
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
18-17.网站域名DNS被劫持,网站服务器密码被改.mp4
QYResearch:2023年前五大2,3,3',4'-联苯四甲酸二酐(α-BPDA)企业占据全球91%的市场份额.docx
2024-2030中国仿生智能餐饮机器人市场现状研究分析与发展前景预测报告
82-82.渗透测试-CVE-2017-8464“震网三代 反弹shell演示课件.mp4
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
渗透测试渗透测试之SQL注入基于报错注入(下)
Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
46-46.渗透测试-Kali Linux安全渗透.mp4
电子元件 电子行业 行业分析 数据分析 数据报告 行业报告
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
【名企实践】华为如何打造高绩效团队glq.pptx
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。