一、Spring数据访问简介
1、Spring数据访问方式
可以使用JDBC、Hibernate、Java持久化API、Mybatis或任意的持久化框架。
2、数据访问模块化
Spring提供了多个可选的模板,如果直接使用JDBC,那可以选择JdbcTemplate。如果使用对象映射框架,可以使用 HibernateTemplate或者JpaTemplate。
模板类(org.springframework.*) | 用途 |
jca.cci.core.CciTemplate | JCA CCI连接 |
jdbc.core.JdbcTemplate | JDBC连接 |
jdbc.core.namedparam.NamedParameterJdbcTemplate | 支持命名参数的JDBC连接 |
jdbc.core.simple.SimpleJdbcTemplate | 通过java5简化后的JDBC连接(Spring3.1中已废弃) |
orm.hibernate3.HibernateTemplate | Hibernate3.X以上的session |
orm.ibatis.SqlMapClientTemplate | ibatis SqlMap客户端 |
orm.jdo.JdoTemplate | java 数据对象(Java Data Object)实现 |
orm.jpa.JpaTemplate | Java持久化API的实体管理器 |
二、配置数据源
1、使用JNDI数据源(推荐使用)(可以参考:https://www.cnblogs.com/xuan52rock/p/4745241.html)
在JavaEE的应用服务器中,都允许通过JNDI获取数据源。这种配置的好处在于数据源完全可以在应用程序之外进行管理,这样应用程序只需要在访问数据库的时候查找数据源就可以了。而且在应用服务器中管理的数据源通常以池的方式组织,具备更好的性能,并且还支持系统管理员对其进行热切换。
JNDI的XML配置:
<jee:jndi-lookup id="dataSource" jndi-name="OracleConnection"></jee:jndi-lookup>
JNDI的Java配置:
@Bean
public JndiObjectFactoryBean dataSource(){
JndiObjectFactoryBean factoryBean = new JndiObjectFactoryBean();
factoryBean.setJndiName("OracleConnection");
factoryBean.setProxyInterface(DataSource.class);
return factoryBean;
}
2、使用数据源连接池(推荐使用)
Spring并没有提供数据源连接池的实现,可以通过DBCP、c3p0、BoneCP实现连接池。
DBCP、c3p0、BoneCP的Maven依赖:
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.jolbox/bonecp -->
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
<version>0.8.0.RELEASE</version>
</dependency>
DBCP、c3p0、BoneCP数据库连接池的三种方式的xml配置:
<!-- 数据源连接池配置三种方式(推荐使用):DBCP、C3P0、BoneCP -->
<!-- DBCP配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="username" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
<!-- C3P0配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="user" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
<!-- BoneCP配置数据源 -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="user" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
DBCP的Java配置(另外两种类似,这里不再展示):
@Bean
public BasicDataSource dataSource(){
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("");
dataSource.setUrl("");
dataSource.setUsername("");
dataSource.setPassword("");
return dataSource;
}
其中在DBCP配置中并不仅仅只有上面的这些配置属性,更多属性见下表:
池配置属性 | 所指定的内容 |
initialSize | 池启动时创建的链接数量 |
maxActive | 同一时间可从池中分配的最多连接数。如果设置为0,表示无限制 |
maxIdle | 池里不会被释放的最多空闲连接数。如果设置为0,表示无限制 |
maxOpenPreparedStatements | 在同一时间能够从语句池中分配的预处理语句(prepared statement)的最大数量,如果设置为0,表示无限制 |
maxWait | 在抛出异常之前,池等待连接回收的最大时间(当没有可用连接时)。如果设置为-1,表示无限等待 |
minEvictableIdleTimeMillis | 连接在池中保持空闲而不被回收的最大时间 |
minIdle | 在不创建新连接的情况下,池中保持空闲的最小连接数 |
poolPreparedStatements | 是否对预处理语句(prepared statement)进行池管理(boolean值) |
3、基于JDBC驱动的数据源(不推荐使用)
①DriverManagerDataSource:在每个连接请求时都会返回一个新的连接,没有进行池化管理
②SimpleDriverDataSource:与DriverManagerDataSource类似,但它是直接使用JDBC驱动的,来解决在特定环境下的类加载问题,这样的环境包括OSGi容器。
③SingleConnectionDataSource:在每个连接请求时,都会返回同一个连接。不适用于多线程应用程序。
以上三种方式的XML配置:
<!-- 基于JDBC驱动的数据源三种方式(不推荐使用) -->
<!--DriverManagerDataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="username" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
<!--SimpleDriverDataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="username" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
<!--SingleConnectionDataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="username" value="scott"></property>
<property name="password" value="scott"></property>
</bean>
DriverManagerDataSource的Java配置(其它两种的Java配置类似,这里不记录):
@Bean
public DriverManagerDataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("");
dataSource.setUrl("");
dataSource.setUsername("");
dataSource.setPassword("");
return dataSource;
}
4、使用嵌入式的数据源(用的比较少,这里不记录)
参考:https://www.cnblogs.com/achengmu/p/8301488.html
5、使用profile选择数据源(用的比较少,这里不记录)
参考:https://blog.csdn.net/qq_33460264/article/details/82426139
三、在Spring中使用JDBC
1、相信在学习Java的过程中都经历过使用原生的JDBC进行数据库的CURD操作,其繁琐估计也是都见过的,首先要创建连接,然后操作数据,操作数据要写一大堆的get、set,操作完成之后还需要关闭连接,而且每一次操作数据库都需要这些步骤。这里就不再赘述这种繁琐的操作了。
2、使用JDBC模板进行数据库的CURD操作。
Spring为JDBC提供了三个模板类:
①JdbcTemplate(推荐):最基本的Spring JDBC模板,这个模板支持简单的JDBC数据库访问功能以及基于索引参数的查询
②NamedParameterJdbcTemplate:使用该模板类执行查询时可以将值以命名参数的形式绑定到SQL中,而不是使用简单的索引参数。
③SimpleJdbcTemplate:该模板利用Java5的一些特性如自动装箱、泛型以及可变参数列表来简化JDBC模板的使用。
3、JdbcTemplate的使用:
在Spring容器中添加JdbcTemplate的bean:
<!-- DBCP配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"></property>
<property name="username" value="scott"></property>
<property name="password" value="scott"></property>
<property name="poolPreparedStatements"></property>
</bean>
<!-- 配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
使用JdbcTemplate的dao类:
package com.mfc.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.mfc.entity.Tuser;
@Repository(value = "tuserDao")
public class TuserDaoImpl implements TuserDao {
@Resource(name = "jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Override
public void add(Tuser tuser) {
String sql = "insert into tuser (userId, userName, userPassword) values (?, ?, ?)";
jdbcTemplate.update(sql, tuser.getUserId(), tuser.getUserName(), tuser.getUserPassword());
}
@Override
public void delete(Tuser tuser) {
String sql = "delete from tuser whete userId = ?";
jdbcTemplate.update(sql, tuser.getUserId());
}
@Override
public void update(Tuser tuser) {
String sql = "update tuser set userName=?, userPassword=? where userId=?";
jdbcTemplate.update(sql, tuser.getUserName(), tuser.getUserPassword(), tuser.getUserId());
}
@Override
public List<Map<String, Object>> find(Tuser tuser) {
String sql = "select * from tUser";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
return list;
}
@Override
public Tuser findByPrimary(String userId) {
String sql = "select * from tUser where userId = ?";
Tuser tuser = jdbcTemplate.queryForObject(sql, new TuserRowMapper(), userId);
return tuser;
}
private static final class TuserRowMapper implements RowMapper<Tuser>{
@Override
public Tuser mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Tuser(rs.getString("userId"), rs.getString("userName"), rs.getString("userPassword"));
}
}
}