spring与数据库编程

在Java互联网编程中,数据大部分存储在数据库和NoSQL工具中;传统的JDBC在执行简单的SQL语句时也需要非常多的代码,包含打开关闭数据库、组装结果等,还有大量的try…catch…finally语句,虽然JDBC的性能是最好的,但代码的可读性和可维护性非常差;
在Spring出现后,Spring提供了JDBC模板模式,就是它自身的JdbcTemplate,可以简化许多代码的编程;但是实际工作中,这个模板也不常用;Spring还提供了支持事务的模板TransactionTemplate,支持Hibernate框架的模板HibernateTemplate,对于MyBatis框架由于版本原因,虽未支持,但MyBatis社区开发了介入Spring的开发包,该包提供了SqlSessionTemplate,且开发者还可以直接使用接口编程;

一、配置数据库资源
配置方式有XML配置或注解,对于项目的公共资源,建议采用XML配置;以XML为例介绍三种配置方式:
(1)使用spring内部提供的类:配置一个最简单的数据源,不支持连接池,一般用于测试;

<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
	<property name="driverClass" value="com.mysql.jdbc.Driver" />
	<property name="url" value="jdbc:mysql://localhost:3306/test"/>
	<property name="username" value="root" />
	<property name="password" value="123456" />
</bean>

(2)使用第三方数据库连接池
需下载对应的数据库连接池相关包,然后在spring中简单配置,示例为DBCP的数据库连接池:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
	<property name="driverClassName" value="com.mysql.jdbc.Driver" />
	<property name="url" value="jdbc:mysql://localhost:3306/chapter13"/>
	<property name="username" value="root" />
	<property name="password" value="123456" /> 
	<property name="maxActive" value="255" /> <!--连接池最大数据库连接数,0表示无限制-->
	<!--连接池中最多可空闲maxIdle个连接 ,这里5表示即使没有数据库连接时依然可以保持5个空闲的连接,而不被清除,随时待命,0表示无限制-->
	<property name="maxIdle" value="5" /> 
	<property name="maxWait" value="10000" /> <!--最大等待毫秒数,-1表示无限制-->
</bean>

(3)使用JNDI数据库连接池

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
	<property name="jndiName" value="java:comp/env/jdbc/test"/>
</bean>

二、使用JdbcTemplate模板
(1)配置JdbcTemplate:在spring配置文件spring-cfg.xml

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	<property name="dataSource" ref="dataSource" />
</bean>

(2)使用JdbcTemplate操作数据库
主要方法:
-execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句(DDL语句包括: create database,create table,alter table ,drop table,create view,alter view ,drop view 等);
-update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
-query方法及queryForXXX方法:用于执行查询相关语句;
-call方法:用于执行存储过程、函数相关语句;

ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("spring-cfg.xml");
JdbcTemplate jt=ctx.getBean(JdbcTemplate.class);
//JDBC增删查改
//增、删、改:jt.update(...)
//查:jt.query(...)、queryForObject(...)

通过ConnectionCallback和StatementCallback接口可获得JdbcTemplate的Statement回调,使用原生的SQL命令,此时,同样可利用JdbcTemplate提供的系列优点,如一致的异常体系;
(PS:回调:定义一个方法A,使用接口作为A的参数,然后在调用此方法时,必须调用这个接口的实现类,在方法A中调用到实现类定义的同名方法时,就会自动执行实现类中自定义的同名方法)

//使用StatementCallback接口进行回调,这个接口只有一个方法需实现Object doInStatement(Statement stmt),
//在该方法的执行体内,可获得Statement的引用,从而完成数据库的操作
public Role getRoleByStatementCallback(JdbcTemplate jdbcTemplate, String id) {
	Role role = null;
     //这里写成Java 8的lambda表达式,如果你使用低版本的Java,需要使用StatementCallback的匿名类
	role = jdbcTemplate.execute((Statement stmt) -> {
		Role result = null;
		String sql = "select id, role_name, note from t_role where id = " + id;
		ResultSet rs = stmt.executeQuery(sql);
		while (rs.next()) {
			result = new Role();
			result.setId(rs.getString("id"));
			result.setNote(rs.getString("note"));
			result.setName(rs.getString("role_name"));
		}
		return result;
	});
	return role;
}

注意,JdbcTemplate不支持事务,如果要支持需要引入对应的事务管理器;在spring中,会在内部判断是否事务交由事务管理器处理,是就从管理器中获取数据库连接,且JdbcTemplate的资源连接的请求关闭也由管理器决定,否数据库资源就有JdbcTemplate自身管理;

三、MyBatis-Spring
MyBatis-Spring项目由MyBatis社区开发,并不是Spring的子框架;
配置MyBatis-Spring项目(mybatis-spring-xxx.jar):
(1)配置数据源,前文已有
(2)配置SqlSessionFactory
MyBatis-Spring项目提供了SqlSessionFactoryBean支持SqlSessionFactory的配置,查看SqlSessionFactoryBean源码可知,其中可以配置几乎所有MyBatis的组件,因此Spring可以通过调用其中的setter方法进行配置;

<!--配置SqlSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="dataSource" />
	<!--MyBatis配置文件,对于简单配置可以选择通过IoC容器注入-->
	<property name="configLocation" value="classpath:sqlMapConfig.xml" />
</bean>

sqlMapConfig.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- 这个配置使全局的映射器启用或禁用缓存 -->
        <setting name="cacheEnabled" value="true" />
        <!-- 允许 JDBC 支持生成的键。需要适合[修改为:适当]的驱动。如果设置为true,则这个设置强制生成的键被使用,尽管一些驱动拒绝兼容但仍然有效(比如 Derby) -->
        <setting name="useGeneratedKeys" value="true" />
        <!-- 配置默认的执行器。SIMPLE 执行器没有什么特别之处。REUSE 执行器重用预处理语句。BATCH 执行器重用语句和批量更新  -->
        <setting name="defaultExecutorType" value="REUSE" />
        <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 设置超时时间,它决定驱动等待一个数据库响应的时间  -->
        <setting name="defaultStatementTimeout" value="25000"/> 
    </settings>
    <!-- 别名配置 -->
    <typeAliases>
        <typeAlias alias="role" type="cn.infocore.pojo.Role" />
    </typeAliases>
 
    <!-- 指定映射器路径 -->
    <mappers>
        <mapper resource="cn/infocore/mapper/RoleMapper.xml" />
    </mappers>
</configuration>

RoleMapper.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.infocore.mapper.RoleMapper">
	<insert id="insertRole" useGeneratedKeys="true" keyProperty="id">
		insert into t_role(role_name, note) values (#{roleName}, #{note})
	</insert>

	<delete id="deleteRole" parameterType="long">
		delete from t_role where id=#{id}
	</delete>

	<select id="getRole" parameterType="long" resultType="role">
		select id, role_name as roleName, note from t_role where id = #{id}
	</select>

	<update id="updateRole" parameterType="role">
		update t_role set role_name = #{roleName},note = #{roleName} where id = #{id}
	</update>
</mapper>

定义命名空间下的接口:

public interface RoleMapper {
	public int insertRole(Role role);
	public Role getRole(@Param("id") String id);
	public int updateRole(Role role);
	public int deleteRole(@Param("id") String id);
}

(3)可选配置SqlSessionTemplate,如果SqlSessionFactory和SqlSessionTemplate都配配置,优先选择SqlSessionTemplate;SqlSessionTemplate的优点是线程安全,即确保每个线程使用的SqlSession唯一且不互相冲突,且提供了一系列的增删查改等功能;
配置SqlSessionTemplate:使用构造器创建对象,常用参数有SqlSessionFactory和MyBatis的执行器Executor类型(SIMPLE,REUSE,BATCH);

<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
	<constructor-arg ref="sqlSessionFactory" />
	<constructor-arg value="BATCH"/>
</bean>

使用SqlSessionTemplate:运行时,每次使用SqlSessionTemplate都会产生一个新的SqlSession,即线程安全;

ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-cfg.xml");
SqlSessionTemplate template=ctx.getBean(SqlSessionTemplate.class);
......
template.insert("cn.infocore.mapper.RoleMapper.insertRole", role);
template.selectOne("cn.infocore.mapper.RoleMapper.getRole", id);
template.update("cn.infocore.mapper.RoleMapper.updateRole", role);
template.delete("cn.infocore.mapper.RoleMapper.deleteRole", id);

但由于SqlSessionTemplate需要通过字符串指定调用哪个SQL,不符合面向对象的规范,且IDE并不能检查这个字符串逻辑的正确性,所以,SqlSessionTemplate的运用也不是很多;
(4)配置Mapper:单个配置或者扫描生成Mapper;
MyBatis-Spring提供了一个MapperFactoryBean类作为中介,可以通过配置来实现我们想要的Mapper;使用Mapper接口式编程可以有效地在逻辑代码中擦除SqlSessionTemplate;
配置RoleMapper对象:mapperInterface:映射器的接口

<bean id="roleMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
   <property name="mapperInterface" value="cn.infocore.mapper.RoleMapper" />
   <property name="sqlSessionFactory" ref="sqlSessionFactory" /> <!--失效-->
   <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
</bean>

RoleMapper role=ctx,getBean(RoleMappper.class);

MapperFactoryBean只能配置一个Mapper,如果Mapper很多就会造成配置量很大的问题,因此我们用MapperScannerConfigurer进行配置,用扫描的方式去生成对应的Mapper;

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="cn.infocore.mapper" />
	<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
	<!-- 使用sqlSessionTemplateBeanName将覆盖sqlSessionFactoryBeanName的配置 -->
	<!-- <property name="sqlSessionTemplateBeanName" value="sqlSessionFactory"/> -->
	<!-- 指定标注才扫描成为Mapper -->
	<property name="annotationClass" value="org.springframework.stereotype.Repository" />
</bean>

RoleMapper接口修改:

@Repository
public interface RoleMapper {...}

除了通过basePackage属性扫描Mapper,还可以使用扩展接口名的方式,由于这个需要定义一个接口,且所有Mapper都要扩展它,比较麻烦,因此不是很推荐,就不详述了;
(5)事务管理,这个见深入spring事务管理

综上所述,推荐使用Spring+MyBatis,配置如下:

<?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 
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

	<!-- 数据库连接池 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/test" />
		<property name="username" value="root" />
		<property name="password" value="infocore" />
		<!--连接池的最大数据库连接数 -->
		<property name="maxActive" value="255" />
		<!--最大等待连接中的数量 -->
		<property name="maxIdle" value="5" />
		<!--最大等待毫秒数 -->
		<property name="maxWait" value="10000" />
	</bean>

	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:sqlMapConfig.xml" />
	</bean>
	
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="cn.infocore.mapper" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
		<property name="annotationClass" value="org.springframework.stereotype.Repository" />
	</bean> 
</beans>

其他需要的文件:xxxMapper.java接口及对应的xxxMapper.xml、sqlMapConfig.xml;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值