它是spring框架中提供的一个对象,是对原始JDBC API对象的简单封装。
spring还提供了很多的操作模板类:
操作关系型数据的:JdbcTemplate,HibernateTemplate
操作nosql数据库的:RedisTemplate
操作消息队列的:JmsTemplate
它就是用于和数据库交互的,实现对表的crud操作
依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
</dependencies>
/**
* jdbctemplate最基本的用法
*/
public class JdbcTemplateDemo1 {
public static void main(String[] args) {
//准备数据源:spring内置数据源
DriverManagerDataSource db = new DriverManagerDataSource();
db.setDriverClassName("com.mysql.jdbc.Driver");
db.setUrl("jdbc:mysql://localhost:3307/test");
db.setUsername("liming");
db.setPassword("liming");
//1.创建jdbctemplate对象
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(db);
//2.执行插入操作
jdbcTemplate.execute("insert into account(name,money) values ('gg',100)");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置账户的持久层-->
<bean id="accountDao" class="com.ming.dao.dbcteplate.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!--配置jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置spring内置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3307/test"></property>
<property name="username" value="liming"></property>
<property name="password" value="liming"></property>
</bean>
</beans>
public class JdbcTemplateDemo2 {
@Test
public void jdbcTemplateTest() {
ApplicationContext ac = new ClassPathXmlApplicationContext("jdbcTemplate.xml");
JdbcTemplate jt = ac.getBean("jdbcTemplate", JdbcTemplate.class);
jt.execute(" insert into account(name,money) values('hh',500)");
}
}
JdbcTemplate的CRUD:
1.测试用
package com.ming.test.jdbctemplate;
import com.ming.model.Account;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* jdbcTemplate的CRUD
*/
public class JdbcTemplateDemo3 {
@Test
public void jdbcTemplateTest() {
ApplicationContext ac = new ClassPathXmlApplicationContext("jdbcTemplate.xml");
JdbcTemplate jt = ac.getBean("jdbcTemplate", JdbcTemplate.class);
//保存
//jt.update(" insert into account(name,money) values(?,?)","lm",200f);
//更新
//jt.update("update account set name =?,money =? where id=? ","xl",1f,8);
//删除
//jt.update("delete from account where id=? ",8);
//查询所有
//List accountList = jt.query("select * from account where money > ? ",new AccountRowMapeer(),10f);
// List accountList = jt.query("select * from account where money > ? ",new BeanPropertyRowMapper<>(Account.class),10f);
// for (Account list : accountList){
// System.out.println(list);
// }
//查询一个
// List accountList = jt.query("select * from account where id = ? ",new BeanPropertyRowMapper<>(Account.class),1);
// System.out.println(accountList.isEmpty()?"null":accountList.get(0));
//查询返回一行一列(使用聚合函数,但不加group by子句)
int count = jt.queryForObject("select count(*) from account where money > ? ", Integer.class, 100f);
System.out.println(count);
}
/**
* 定义封装account
*/
class AccountRowMapeer implements RowMapper<Account> {
@Override
public Account mapRow(ResultSet resultSet, int rowNum) throws SQLException {
Account account = new Account();
account.setId(resultSet.getInt("id"));
account.setName(resultSet.getString("name"));
account.setMoney(resultSet.getFloat("money"));
return account;
}
}
}
2.实际开发中:
持久层接口
package com.ming.dao.dbcteplate;
import com.ming.model.Account;
/**
* 基于jdbcTemplate的持久层
*/
public interface IAccountDao {
/**
* 根据id查询账户
* @param accountId
* @return
*/
Account findAccountById(Integer accountId);
/**
* 根据账户名称查询账户
* @param accountName
* @return
*/
Account findAccountByName(Integer accountName);
/**
* 更新账户
* @param account
*/
void updateAcocount(Account account);
}
持久层实现类
package com.ming.dao.dbcteplate.impl;
import com.ming.dao.dbcteplate.IAccountDao;
import com.ming.model.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
/**
* 基于jdbcTemplate的账户持久层实现类
*/
public class AccountDaoImpl implements IAccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public Account findAccountById(Integer accountId) {
List<Account> accountList = jdbcTemplate.query("select * from account where id = ? ",new BeanPropertyRowMapper<Account>(Account.class),accountId);
return accountList.isEmpty()?null:accountList.get(0);
}
@Override
public Account findAccountByName(Integer accountName) {
List<Account> accountList = jdbcTemplate.query("select * from account where name = ? ",
new BeanPropertyRowMapper<Account>(Account.class),accountName);
if(accountList.isEmpty()){
return null;
}
if(accountList.size() > 1){
throw new RuntimeException("结果集不为1");
}
return accountList.get(0);
}
@Override
public void updateAcocount(Account account) {
jdbcTemplate.update("update account set name = ? , money = ? where id = ? ",account.getName(),account.getMoney(),account.getId());
}
}
测试
public class JdbcTemplateDemo3 {
@Test
public void jdbcTemplateDaoTest(){
ApplicationContext ac = new ClassPathXmlApplicationContext("jdbcTemplate.xml");
IAccountDao accountDao = ac.getBean("accountDao", IAccountDao.class);
Account account = accountDao.findAccountById(7);
System.out.println(account);
account.setMoney(959f);
accountDao.updateAcocount(account);
}
}
1.JdbcDaoSupport的使用
第一种方式:抽取持久层dao,写一个类JdbcDaoSupport用于让dao的实现类继承
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置账户的持久层-->
<bean id="accountDao" class="com.ming.dao.dbcteplate.impl.AccountDaoImpl">
<!-- <property name="jdbcTemplate" ref="jdbcTemplate"></property>-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置jdbcTemplate-->
<!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">-->
<!-- <property name="dataSource" ref="dataSource"></property>-->
<!-- </bean>-->
<!--配置spring内置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3307/test"></property>
<property name="username" value="liming"></property>
<property name="password" value="liming"></property>
</bean>
</beans>
package com.ming.dao.dbcteplate.impl;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
/**
* 此类用于抽取dao层中的重复代码
*/
public class JdbcDaoSupport {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
//this.dataSource = dataSource;
if(jdbcTemplate == null){
jdbcTemplate = createJdbcTemplate(dataSource);
}
}
private JdbcTemplate createJdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
package com.ming.dao.dbcteplate.impl;
import com.ming.dao.dbcteplate.IAccountDao;
import com.ming.model.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import java.util.List;
/**
* 基于jdbcTemplate的账户持久层实现类
*/
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
@Override
public Account findAccountById(Integer accountId) {
List<Account> accountList = super.getJdbcTemplate().query("select * from account where id = ? ",new BeanPropertyRowMapper<Account>(Account.class),accountId);
return accountList.isEmpty()?null:accountList.get(0);
}
@Override
public Account findAccountByName(Integer accountName) {
List<Account> accountList = super.getJdbcTemplate().query("select * from account where name = ? ",
new BeanPropertyRowMapper<Account>(Account.class),accountName);
if(accountList.isEmpty()){
return null;
}
if(accountList.size() > 1){
throw new RuntimeException("结果集不为1");
}
return accountList.get(0);
}
@Override
public void updateAcocount(Account account) {
super.getJdbcTemplate().update("update account set name = ? , money = ? where id = ? ",account.getName(),account.getMoney(),account.getId());
}
}
2.Dao的两种编写方式
如果不自己写第一种方式JdbcDaoSupport用spring的只要继承就行,spring会自动导入:
import org.springframework.jdbc.core.support.JdbcDaoSupport;
继续JdbcDaoSupport的作用:去除dao的注入和定义的重复代码
区别:如果自己编写的类用@Autowired private JdbcTemplate jdbcTemplate;可以使用
但是只要继承spring的JdbcDaoSupport在jar上加上注解就比较难实现
javax.sql.DataSource。DataSource的创建可以有不同的实现。
JNDI方式创建DataSource
以JNDI方式创建数据源首先要配置数据源的相关连接信息,也就是数据源连接池。该配置应该在Tomcat安装目录下的conf/context.xml文件中配置。其配置如下:
……
然后,在程序中以JNDI的方式创建数据源,得到数据库连接已进行相应的操作。代码如下: Apache提供的简单连接池创建数据源 以这种方式创建数据源必须先准备两个jar文件:commons-dbcp.jar 和 commons-pool.jar。 以这种方式创建的数据源就不再是javax.sql.DataSource。DataSource了,而是org.apache.commons.dbcp.BasicDataSource。而且不再需要配置任何文件就可以直接使用。代码如下: 创建BasicDataSource对象 C3P0方式创建数据源 Proxool方式创建数据源 BoneCP方式创建数据源 创作者称,BoneCP在性能上会完全超越所有主流的Java连接池。它可以帮你管理数据连接,让你的应用程序能更快速地访问数据库。比C3P0/DBCP(DataBaseconnection pool,数据库连接池)连接池快25倍。这个数据库连接池采用Google Collection作为内部的集合类框架,而且现在的版本已经很稳定。 要使用BoneCP,必须用到的jar文件有: · bonecp-0.6.5.jar · google-collections-1.0.jar · slf4j-api-1.5.11.jar · slf4j-log4j12-1.5.11.jar ·log4j-1.2.15.jar 在程序中创建BoneCPDataSource对象,代码如下: // 创建BoneCPDataSource对象 ds.setMinConnectionsPerPartition(2); ds.setPartitionCount(2); 以上几种创建数据源的方式多以硬编码来实现,在实际应用中应该以配置文件的形式出现,以方便管理和维护。 type="javax.sql.DataSource"maxActive="100" maxIdle="30"
maxWait="10000"username="root" password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/cheng"/>
……
// 初始化JNDI上下文,创建DataSource对象
Context initContext = new InitialContext();
Context context = (Context)initContext.lookup("java:comp/env");
DataSourcedataSource = (DataSource)context.lookup("jdbc/NutzDemo");
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("root");
ds.setPassword("root");
ds.setInitialSize(50);
ds.setMaxActive(100);
ds.setMaxIdle(30);
ds.setMaxWait(10000);
// 关闭数据源连接
ds.close();
使用C3P0方式创建数据源应该首先准备一个jar文件:c3p0-0.9.1.2.jar,将其放到web/lib目录下,就可以在项目中使用C3P0创建数据源,C3P0创建的数据源对象也不是DataSource对象,而是ComboPooledDataSource,代码如下:
// 创建ComboPooledDataSource对象
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUser("root");
ds.setPassword("root");
ds.setInitialPoolSize(50);
ds.setMaxPoolSize(100);
ds.setMaxIdleTime(10000);
应该准备的jar文件为:proxool-01.9.0RC3.jar,之后在项目中创建ProxoolDataSource对象,其代码如下:
// 创建ProxoolDataSource对象
ProxoolDataSource ds = new ProxoolDataSource();
ds.setDriver("com.mysql.jdbc.Driver");
ds.setDriverUrl("jdbc:mysql://localhost:3306/cheng");
ds.setUser("root");
ds.setPassword("root");
BoneCP是一个快速高效,开源免费的Java数据库接池。
BoneCPDataSource ds = new BoneCPDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/cheng");
ds.setUsername("root");
ds.setPassword("root");
ds.setAcquireIncrement(1);
ds.setAcquireRetryDelay(10000);
ds.setIdleConnectionTestPeriod(100);
ds.setMaxConnectionsPerPartition(20);