JAVA WEB之Spring4.x JdbcTemplate
jdbcTemplate
说白了,他就是Spring提供用于简化数据库访问的类
基本jdbc驱动访问数据库
/* 一个简易好用的数据库连接和访问类 */
package cslg.cn.controller;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class MyDB {
private static final String database="bookmark";
private static final String user="root";
private static final String password="";
private Connection connection;
private Statement statement;
public void openConnection() throws SQLException{
try {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/"+database;
connection=DriverManager.getConnection(url, user, password);
statement=connection.createStatement();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void closeConnection(){
try {
if(statement!=null){
statement.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ResultSet executeQuery(String sql) throws SQLException {
ResultSet rs=statement.executeQuery(sql);
return rs;
}
void executeUpdate(String sql) throws SQLException {
statement.executeUpdate(sql);
}
}
基本思路就是:
- 连接数据库时的字符串常量,变量
- 加载jdbc类库
- 获得一个连接
- 获得一个连接的状态
- 通过状态使用query或者update访问数据库
基本可用的也就是读写两个方法:
statement.executeQuery(sql)
statement.executeUpdate(sql)
我们还需要对query方法返回的ResultSet类进行处理:
while (res.next()) {
BookMark bm = new BookMark(res.getInt(1), res.getString(2), res.getString(3), res.getString(4),res.getInt(5));
bms.add(bm);
}
如果时多条数据查询,一般需要一个数据模型类(pojo类),然后建立一个这个模型的List泛型对象,通过ResultSet的next()方法遍历每一条记录,使用getInt,getString等方式取得字段。
Spring JdbcTemplate访问数据库
如果我们使用像hibernate,mybatits这样的orm的话,虽然模型映射为sql语句确实非常方便,但是性能上就有一定阉割,在不需要大量数据查询的小型项目上,我们不用偷懒,写几句简单的sql语句使得查询和写入更加有效率。
但是我们像上面那样每次都通过while语句去取出Result的话,岂不是很麻烦,而且这样的多个while代码块显得代码十分冗余。
JdbcTemplate为我们封装了这些取值操作,减少了写循环的痛苦,性能上却并没有被阉割,和纯粹的sql语句查询相当,因为我们依然要写出完整的sql语句,而不是采用映射的办法,所以这个template非常好用的。
项目结构
由于仅仅是学习测试jdbctemplate,所以不需要web访问,使用Main方法运行,自然建立普通的gradle project即可,并不需要转换
结构也只需要对java resource添加java类即可:
配置
配置xml文件,properties文件
如果是web dynamic项目的话xml文件可以web-inf下新建config.xml或者直接在java Resource目录下新建
config.xml,我使用了4.3版本:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<context:annotation-config />
<context:component-scan base-package="jdbc"></context:component-scan>
<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="jdbc" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />
</beans>
以上对各种Bean做了配置,用于提供JdbcTemplate连接数据库
jdbc.properties:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/j2ee?characterEncoding=utf8
jdbc.username=root
jdbc.password=
如果是gradle项目:
修改gradle.build以获得需要的jar包:
apply plugin: 'java-library'
// In this section you declare where to find the dependencies of your project
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
ext{
springVersion="4.3.1.RELEASE"
}
dependencies {
compile group: 'org.slf4j', name:'slf4j-api', version:'1.7.21'
compile group: 'commons-codec', name: 'commons-codec', version: '1.10'
compile group: 'commons-collections', name: 'commons-collections', version: '3.2.2'
compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'
compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.8.9'
compile group: 'aopalliance', name: 'aopalliance', version: '1.0'
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.38'
compile(
"org.springframework:spring-core:$springVersion",
"org.springframework:spring-beans:$springVersion",
"org.springframework:spring-aop:$springVersion",
"org.springframework:spring-tx:$springVersion",
"org.springframework:spring-jdbc:$springVersion",
"org.springframework:spring-context:$springVersion",
"org.springframework:spring-test:$springVersion"
)
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:20.0'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
}
POJO类
该Project是对数据库文章进行增删改查,所以,我新建了一个Article类,为数据库Article表模型:
package jdbc;
public class Article {
private int id;
private String title;
private String content;
@Override
public String toString() {
return "Article [id=" + id + ", title=" + title + ", content=" + content + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Article(int id, String title, String content) {
super();
this.id = id;
this.title = title;
this.content = content;
}
public Article(String title, String content) {
super();
this.title = title;
this.content = content;
}
public Article(){
}
}
Article的DAO层
在面向接口对象编程中
MVC的开发模式:表示层调用控制层,控制层调用业务层,业务层(Service)调用数据访问层(DAO)
就是这样层层剥离,解耦,使得一个层的修改不会导致其他层的修改,更利于团队分层并行编程
当然如果使用的是动态语言,比如php,是不需要剥离出这么多层这么麻烦的!
其中dao是数据访问层,其实是一个集成了一些专门对某个模型直接访问数据库方法的类,比如增删改查等,便于在业务逻辑层(service层)使用这些方法,操作相应的模型,而hibernate这样的orm则是通过映射来封装了相应的模型访问数据库方法,做成了DAO层,不必自己去写
ArticleDAO:
package jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
@Repository
public class ArticleDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
// 查
public Article find(int id) {
final String sql = "select * from article where id=?";
Article ac = jdbcTemplate.queryForObject(sql, new Object[] { id },
new BeanPropertyRowMapper<Article>(Article.class));
return ac;
}
// 改
public boolean update(Article a) {
final String sql = "update article set title=?,content=? where id=?";
int rc = jdbcTemplate.update(sql, new Object[] { a.getTitle(), a.getContent(), a.getId() });
return 1 == rc;
}
// 删
public boolean delete(int id) {
final String sql = "delete from article where id=?";
int rc = jdbcTemplate.update(sql, new Object[] { id });
return 1 == rc;
}
// 增
public int add(Article a) {
KeyHolder holder = new GeneratedKeyHolder();
final String sql = "insert into article(title,content) values(?,?)";
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, a.getTitle());
ps.setString(2, a.getContent());
return ps;
}
}, holder);
return holder.getKey().intValue();
}
//根据开始和限定条数查询多条
public List<Article> list(int begin, int limit) {
final String sql = "select * from article limit ?,?";
return jdbcTemplate.query(sql, new Object[] { begin, limit },
new BeanPropertyRowMapper<Article>(Article.class));
}
}
注意DAO层提供对数据的访问方法库,这里包括了常用的CRUD操作,其中查方法有两种,一种是单条根据主键查询(id),另一种是指定条数开始和数目的多条查询(limit),这里需要用到一个数据库对Bean的映射。
由于jdbcTemplate中的queryForObject方法,第三个参数只能是匹配简单的Interger,String,Boolean等基本类型,不可以传入复杂的数据类型,这里直接传入Article.class是会报异常:
Exception in thread "main" org.springframework.jdbc.IncorrectResultSetColumnCountException: Incorrect column count: expected 1, actual 3
如果是Junit环境下测试是不会获得此List对象(不匹配,不报异常)
所以使用BeanPropertyRowMapper(T.class),此方法的作用是让数据库读出的数据行的字段和java类下的属性一一对应(赋值)。queryForObject的最终效果是要让查询获得row自动匹配到相应的java对象!
(这已经很接近orm技术了!)
注:自动绑定,需要列名称和Java实体类名字一致,如:属性名 “userName” 可以匹配数据库中的列字段 "USERNAME" 或 “user_name”。
关于query和queryForObject的区别:
eclipse自动补全中有说明:
query:传入sql语句,对应的占位对象数组(就是sql中?),RowMapper映射对象。
最终返回的也是RowMapper映射的对象的List列表!
注意是列表!一般用于多条查询的
queryForObject:传入sql,对应的占位对象数组(sql中的?),基本对象的.class属性,或者RowMapper
如果是基本对象Integer,Boolean等则返回相应的与第三个传入参数一样的对象(.class前面的类名)
如果是RowMapper则返回映射后的对象,即第三个参数.class前面的类名!
注:这儿是单个对象,一般用于单条查询
MAIN方法
由于我们是相对简单的应用,不再需要Service层做业务处理,可以直接使用此DAO层进行数据访问,写在Main方法中即可:
main:
package jdbc;
import java.util.Scanner;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
@SuppressWarnings("resource")
public static void main(String[] args) {
//加载xml配置文件
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:config.xml");
//取得Bean类并且映射为DAO类
ArticleDAO aDAO = ctx.getBean(ArticleDAO.class);
int id = 0;
Scanner s = new Scanner(System.in);
while (true) {
System.out.println("输入查询id:");
id = s.nextInt();
try {
Article a = aDAO.find(id); // 传入id查询
System.out.println(a);
} catch (Exception e) {
//抛出查不到的异常,不要让查询错误使得程序结束
System.out.println("查询不到结果!");// 传入id找不到就报错
}
System.out.println();
}
}
}
测试结果:
尝试其他的DAO方法(list查询):
JAVA WEB之Spring4.x JdbcTemplate的更多相关文章
- 【Java Web开发学习】Spring4整合thymeleaf视图解析
[Java Web开发学习]Spring4整合thymeleaf视图解析 目录 1.简单介绍2.简单例子 转载:https://www.cnblogs.com/yangchongxing/p/9111 ...
- 【Java Web开发学习】Spring4条件化的bean
[Java Web开发学习]Spring4条件化的bean 转载:https://www.cnblogs.com/yangchongxing/p/9071960.html Spring4引入了@Con ...
- Java Web整合开发实战:基于Struts 2+Hibernate+Spring 目录
第1篇 Java Web开发基础第1章 Web的工作机制( 教学视频:31分钟) 1.1 理解Web的概念 1.1.1 Web的定义 1.1.2 Web的三个核心标准 1.2 C/S与B/S两种软件体 ...
- 从事务角度粗窥架构的可扩展性和可维护性:内容整理自java web轻量级开发面试教程
大家多少了解过架构,也听说过使用架构后,代码和可维护性和重用性能大大提升.这里我们来通过一些关于事务的实例,来感性地体会下架构带来的在可维护性方面的便利.本文来是从 java web轻量级开发面试教程 ...
- Java Web基础入门
前言 语言都是相通的,只要搞清楚概念后就可以编写代码了.而概念是需要学习成本的. Java基础 不用看<编程思想>,基础语法看 http://www.runoob.com/java/jav ...
- java web 整合开发王者归来学习总结
第一章java web开发概述 胖客户端CS,瘦客户端BS(Browser) 网址请求---服务器处理响应-----返回结果-----浏览器显示 CGI可以动态生成页面,但是每个进程都要启动一个CGI ...
- JAVA WEB快速入门之从编写一个基于SpringMVC框架的网站了解Maven、SpringMVC、SpringJDBC
接上篇<JAVA WEB快速入门之通过一个简单的Spring项目了解Spring的核心(AOP.IOC)>,了解了Spring的核心(AOP.IOC)后,我们再来学习与实践Maven.Sp ...
- 使用IDEA结合MAVEN创建一个Spring Java Web项目
前言 如今的Java项目,如果还使用传统的把jar包复制到目录下这种原始的方式,对于依赖管理来说实在是灾难.对某个功能需要引入某种技术包,但是你不确定是否已存在,如果分类好的话还好找,若是杂在一堆不仅 ...
- Java Web项目实战第1篇之环境搭建
写在前面的话 从今天开始一个Java Web实战项目,参考自 http://blog.csdn.net/eson_15/article/details/51277324 这个博客(非常感谢博主的分享精 ...
随机推荐
- JavaScript学习点滴 call、apply的区别
对于apply和call两者在作用上是相同的,但两者在参数上有区别的. 1.call call 方法 调用一个对象的一个方法,以另一个对象替换当前对象. call([thisObj[,arg1 ...
- IE iframe cookie问题(p3p)
IE iframe cookie问题(p3p) 前段时间碰到一个问题,就是在IE下,使用iFrame嵌入页面时,该页面的会话级别的cookie无法写入,导致服务端始终无法获取JSESSIONID,每次 ...
- 阿里云服务器Tomcat无法从外部访问
一.环境 阿里云 Ubuntu 12.04.5 LTS tomcat和java都是阿里云默认的7的版本,如下图 二.问题 部署后./startup.sh启动tomcat 之后外部访问http://ip ...
- MariaDB扩展特性--虚拟列
存在于表中的列,它们的值是根据确定的表达式或者是根据表中其他列的值自动计算的. 虚拟列有两种,分别对应了定义虚拟列的修饰关键词: 'VIRTUAL'修饰词含义为该虚拟列的值会在查询的时候计算生成. ' ...
- better-scroll不能滚动之 滚动监听-左右联动
滚动监听 better-scroll 无法滚动的分析,直接翻到最后,看问题汇总,希望能帮助你解决. 借用一下人家这个好看的项目图片,做一个解释.左边的内容会跟右边的内容一起关联,点击左边的菜单,右边会 ...
- ASP.NET Core中使用IOC三部曲(一.使用ASP.NET Core自带的IOC容器)
前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...
- jdk1.8新特性 : 接口中可以有普通方法(非静态方法)和静态方法 , 颠覆了之前我的理解 : 接口中只能有共有常量和抽象方法的概念,后面必须要加一句jdk1.7和1..7之前
看到jdk某些接口中存在default方法,于是... http://shaomeng95.iteye.com/blog/998820 为什么接口只能是公有常量? public interfac ...
- udev实现热插拔
一.UDEV是什么? Udev是一个针对Linux内核2.6的可提供自动创建的设备节点和命名的解决方法的一个文件系统:其实与/etc/目录下的fstab文件类似 二.Udev如何获取内核这些模块的变化 ...
- JavaSE(十一)之异常处理详解
一.异常概述 在我们日常生活中,有时会出现各种各样的异常,例如:职工小王开车去上班,在正常情况下,小王会准时到达单位.但是天有不测风云,在小王去上班时,可能会遇到一些异常情况,比如小王的车子出了故障, ...
- Hat's Fibonacci(大数加法+直接暴力)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1250 hdu1250: Hat's Fibonacci Time Limit: 2000/1000 M ...