我们今天的主角在 spring-jdbc-5.0.2.RELEASE.jar 中,我们在导包的时候,除了要导入这个 jar 包 外,
还需要导入一个 spring-tx-5.0.2.RELEASE.jar(它是和事务相关的)
、
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=8438031100
<aop:config>:配置aop的开始标签 aop:实现的办法是利用动态代理
<aop:pointcut> 切入点:也就是将连接点增强的办法(切入点)
切入点表达式的写法:
关键字:execution(表达式)
表达式:
访问修饰符 返回值 包名.包名.包名...类名.方法名(参数列表)
标准的表达式写法:
public void com.itheima.service.impl.AccountServiceImpl.saveAccount()
访问修饰符可以省略
void com.itheima.service.impl.AccountServiceImpl.saveAccount()
返回值可以使用通配符,表示任意返回值
* com.itheima.service.impl.AccountServiceImpl.saveAccount()
包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.
* *.*.*.*.AccountServiceImpl.saveAccount())
包名可以使用..表示当前包及其子包
* *..AccountServiceImpl.saveAccount()
类名和方法名都可以使用*来实现通配
* *..*.*()
参数列表:
可以直接写数据类型:
基本类型直接写名称 int
引用类型写包名.类名的方式 java.lang.String
可以使用通配符表示任意类型,但是必须有参数
可以使用..表示有无参数均可,有参数可以是任意类型
全通配写法:
* *..*.*(..)
实际开发中切入点表达式的通常写法:
切到业务层实现类下的所有方法
* com.itheima.service.impl.*.*(..)
<aop:aspect>切面 也就是切入点(连接点增强的办法)和同事(事务)的结合
id 切面的唯一标识
ref="txManager" 事务的bean唯一标识
两种加起来就是切面(切入点和通知的结合)
<aop:before 配置前置通知:开启事务>
<aop:after-returning 配置后置通知:提交事务->
<aop:after-throwing 配置异常通知:回滚事务>
<aop:after 配置最终通知:释放连接>
<aop:around 配置环绕通知 详细的注释请看Logger类中>配置环绕通知:
也就是整个invoke()办法,可以在里面配置前置,后置,异常,最后通知和切入点办法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}
</aop:aspect>
<aop:config>
<aop:pointcut id="pt1" expression="execution(* com.sise.servlet.impl.*.*(..))"/>
<aop:aspect id="txAdvice" ref="txManager">
<!--配置前置通知:开启事务-->
<aop:before method="beginTransaction" pointcut-ref="pt1"/>
<!--配置后置通知:提交事务-->
<aop:after-returning method="commitTransaction" pointcut-ref="pt1"/>
<!--配置异常通知:回滚事务-->
<aop:after-throwing method="rollbackTransaction" pointcut-ref="pt1"/>
<!--配置最终通知:释放连接-->
<aop:after method="closeTransaction" pointcut-ref="pt1"/>
<aop:around method="aroundTransaction" pointcut-ref="pt1"/>
</aop:aspect>
</aop:config>
记住用spring提供的内置事务管理器,就不需要线程和当前链接绑定(也就是说ConnectionUtils这个类可以删除)
而且Impl.daoimpl类中的sqlq语句不能加Connectionutils.getThreadConnection(),否则事务失败,spring本身已经弄好了
<!-- spring中基于XML的声明式事务控制配置步骤
1、配置事务管理器
2、配置事务的通知
此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的
使用tx:advice标签配置事务通知
属性:
id:给事务通知起一个唯一标识
transaction-manager:给事务通知提供一个事务管理器引用
3、配置AOP中的通用切入点表达式
4、建立事务通知和切入点表达式的对应关系
5、配置事务的属性
是在事务的通知tx:advice标签的内部
-->
<!-- 配置事务管理器
需要提供数据源,用来绑定线程和连接
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<!-- 配置事务的通知
transaction-manager》》》》事务管理器的唯一id标识
-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 配置事务的属性
isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。一部可以不写
propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
一般》》》propagation="REQUIRED" read-only="false"
和》》》》propagation="SUPPORTS" read-only="true"
两者同时出现
read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。
-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
</tx:attributes>
</tx:advice>
<!-- 配置aop-->
<aop:config>
<!-- 配置切入点表达式-->
<aop:pointcut id="pt1" expression="execution(* com.sise.servlet.impl.*.*(..))"></aop:pointcut>
<!--建立切入点表达式和事务通知的对应关系
建立一个切面》》
需要事务和切入点
advice-ref="txAdvice"(事务)
pointcut-ref="pt1"(切入点)
-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>
测试类
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = "bean.xml")这样就会出现出错,找不到该类,必须加classpath:说明该文件是再根路径下
@ContextConfiguration(locations = "classpath:bean.xml")
/*
* 下面这句话等价于---> ApplicationContext acs = new ClassPathXmlApplicationContext("bean.xml");
IUserServlet ac = (IUserServlet) acs.getBean("userServlet");
* 就是类似加载了bean.xml,又因为完成注解已经用SpringConfiguration类替代了bean.xml,故加载这个就等价加载bean.xml
*
*
*
* @ContextConfiguration 注解:
* locations 属性:用于指定配置文件的位置。如果是类路径下,需要用 classpath:表明
* classes 属性:用于指定注解的类。当不使用 xml 配置时,需要用此属性指定注解类的位置
* */
//@ContextConfiguration(classes = SpringConfiguration.class)
public class test {}
@Autowired @Qualifier("userServlet") private IUserServlet userServlet; //目前IUserServlet有三个对象名,Autowired这样就不行,无法自动授予那个对象, 因此需要Qualifier对那个名字进行授权 //这个是注解和xml配置的实现办法
/*
* @ContextConfiguration(locations = "classpath:bean.xml")作用是:获取容器,有了这句话就不需要下面这2句话
*
*
ApplicationContext acs = new ClassPathXmlApplicationContext("bean.xml");
IUserServlet ac = (IUserServlet) acs.getBean("userServlet");也是为了获取容器
*
*
这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常。所以又不能轻易删掉。
@ContextConfiguration(classes = SpringConfiguration.class)
@RunWith(SpringJUnit4ClassRunner.class)
这两句话不写,直接用junit不行,会提示 @Autowired对象空指针异常,原因在下面
* 针对上述问题,我们需要的是程序能自动帮我们创建容器。
* 一旦程序能自动为我们创建 spring 容器,我们就 无须手动创建了,
* 问题也就解决了。 我们都知道,junit 单元测试的原理(在 web 阶段课程中讲过),
* 但显然,junit 是无法实现的,因为它自 己都无法知晓我们是否使用了 spring 框架,
* 更不用说帮我们创建 spring 容器了。不过好在,junit 给我们暴露 了一个注解,
* 可以让我们替换掉它的运行器。 这时,我们需要依靠 spring 框架,
* 因为它提供了一个运行器,可以读取配置文件(或注解)来创建容器。我 们只需要告诉它配置文件在哪就行了。
*
* @ContextConfiguration(classes = SpringConfiguration.class)
@RunWith(SpringJUnit4ClassRunner.class)这两句话就是这个作用,用来替换
* ApplicationContext acs = new ClassPathXmlApplicationContext("bean.xml");
IUserServlet ac = (IUserServlet) acs.getBean("userServlet");来获取容器
* */
// ApplicationContext acs = new ClassPathXmlApplicationContext("bean.xml");
// IUserServlet ac = (IUserServlet) acs.getBean("userServlet");
动态代理
@Component("beanFactory")
public class BeanFactory {
@Autowired
private TransactionManager txManager;
public void setTxManager(TransactionManager txManager) {
this.txManager = txManager;
}
public void setUserServlet(IUserServlet userServlet) {
this.userServlet = userServlet;
}
@Autowired
private IUserServlet userServlet;
//proxyUserServlet代理对象的bean
//userServlet被代理对象的bean
/*
* 基于接口的动态代理-->也就是被代理的对象userServlet必须实现接口
动态代理:
* 特点:字节码随用随创建,随用随加载
* 作用:不修改源码的基础上对方法增强
* 分类:
* 基于接口的动态代理
* 基于子类的动态代理
* 基于接口的动态代理:
* 涉及的类:Proxy
* 提供者:JDK官方
* 如何创建代理对象:
* 使用Proxy类中的newProxyInstance方法
* 创建代理对象的要求:
* 被代理类最少实现一个接口,如果没有则不能使用
* 也就是被代理的对象userServlet必须是实现接口的类对象
*
* 参数1:ClassLoader loader---> 它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
通俗点就是想代理那个对象,就写这个对象的字节码类加载器
参数2:Class<?>[] interfaces--->它是用于让代理对象和被代理对象有相同方法。固定写法。
* 通俗点就是让代理对象和被代理对象都有相同的办法,这样被代理对象(userServlet)可以直接调用
* 代理对象(proxyUserServlet)也可以直接调用
参数3:InvocationHandler对象---> 它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
* 此接口的实现类都是谁用谁写
*
* 参数含义:
* ClassLoader:和被代理对象使用相同的类加载器。
* Interfaces:和被代理对象具有相同的行为。实现相同的接口。
* InvocationHandler:如何代理。
* 策略模式:使用场景是:
* 数据有了,目的明确。
* 如何达成目标,就是策略。
*
*
* 参数1:Object proxy--->代理对象
* 参数2:Method method--->当前执行的办法
* 参数3:Object[] args--->当前执行办法所需的参数,数组从0开始
*
* */
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行代理对象的办法");
Object rtValue = null;
//提供增强的代码
if ("test".equals(method.getName())) {
return method.invoke(userServlet, args);
}
try {
txManager.beginTransaction();
if ("transfer".equals(method.getName())) {
System.out.println("动态代理-->transfer");
args[2] = 1000;
}
rtValue = method.invoke(userServlet, args);
txManager.commitTransaction();
return rtValue;
} catch (Exception e) {
txManager.rollbackTransaction();
throw new RuntimeException(e);
} finally {
txManager.commitTransaction();
}
}
};
@Bean("proxyUserServlet")
public IUserServlet getIUserServlet() {
return (IUserServlet) Proxy.newProxyInstance(
userServlet.getClass().getClassLoader(),
userServlet.getClass().getInterfaces(),
handler
);
}
}
// @Bean("EnhancerBeanFactory")
public IUserServlet getUserServlet() {
return (IUserServlet) Enhancer.create(userServlet.getClass(), userServlet.getClass().getInterfaces(), new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
/**
* 执行IUserServlet类任何方法都会经过该方法
* @param proxy:代理对象
* @param method:当前执行的办法
* @param args:当前执行办法所需的参数
* 以上三个参数和基于接口的动态代理中invoke方法的参数是一样的
* @param methodProxy :当前执行方法的代理对象
* @return
* @throws Throwable
*/
System.out.println("执行代理对象的 Enhancer.create办法");
Object rtValue = null;
//提供增强的代码
if ("test".equals(method.getName())) {
return method.invoke(userServlet, args);
}
try {
txManager.beginTransaction();
if ("transfer".equals(method.getName())) {
System.out.println("动态代理-->transfer");
// args[2] = 1000;//java.lang.IllegalArgumentException: argument type mismatch
//这个错误就是说参数类型不一致,因为userServlet.transfer("王成","王妃", (float) 500)
//最后一个参数是float
//args[2] = 1000;这个是int型,因此需要args[2] = 1000f;让他也是float
args[2] = 1000f;
}
rtValue = method.invoke(userServlet, args);
txManager.commitTransaction();
return rtValue;
} catch (Exception e) {
txManager.rollbackTransaction();
throw new RuntimeException(e);
} finally {
txManager.commitTransaction();
}
}
});
}
}
JdbcConfig.java
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean("dataSource")
public DataSource createDataSource() {
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass(driver);
cpds.setJdbcUrl(url);
cpds.setUser(username);
cpds.setPassword(password);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return cpds;
}
@Bean("template")
public JdbcTemplate returnTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean("runner")
public QueryRunner returnrunner(DataSource dataSource) {
return new QueryRunner(dataSource);
}
}
线程和链接绑定
//数据库连接工具类:目 目的就是将当前线程和当前连接绑定,使得事务正常进行
//而不是每次都进行连接的创建,也就是银行转账问题,没有事务因此每次执行对数据库的操作都创建连接
//因此会让数据不一致
@Component("connectionUtils")
public class ConnectionUtils {
private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
@Autowired
private DataSource dataSource;
public Connection getConnection() {
try {
//1.先从ThreadLocal上获取
Connection conn = tl.get();
//2.判断当前线程上是否有连接
if (conn == null) {
//3.从数据源中获取一个连接,并且存入ThreadLocal中
conn = dataSource.getConnection();
tl.set(conn);
}
//4.返回当前线程上的连接
return conn;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void CloseConnection() {
tl.remove();
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
@Configuration
@ComponentScan(basePackages = "com.sise")
@Import({JdbcConfig.class})
@PropertySource("classpath:jdbc.properties")
@EnableAspectJAutoProxy
//如果要用注解来配置AOP的支持和切面,只能用环绕通知,用前置,后置,最终,异常配置不了,这个只能支持xml配置
public class SpringConfiguration {
}
/**
* 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
*/
@Component("txManager")
public class TransactionManager {
@Autowired
private ConnectionUtils connectionUtils;
public void setConnectionUtils(ConnectionUtils connectionUtils) {
this.connectionUtils = connectionUtils;
}
/**
* 开启事务
*/
public void beginTransaction() {
try {
System.out.println("配置前置通知:TransactionManager在切入点方法执行之前执行");
connectionUtils.getConnection().setAutoCommit(false);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 提交事务
*/
public void commitTransaction() {
try {
System.out.println("配置后置通知:TransactionManager在切入点方法正常执行之后值。它和异常通知永远只能执行一个");
connectionUtils.getConnection().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 回滚事务
*/
public void rollbackTransaction() {
try {
System.out.println("配置异常通知:TransactionManager在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个");
connectionUtils.getConnection().rollback();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 关闭事务
*/
public void closeTransaction() {
try {
System.out.println("配置最终通知:TransactionManager无论切入点方法是否正常执行它都会在其后面执行");
connectionUtils.getConnection().close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 环绕通知事务
*/
public Object aroundTransaction(ProceedingJoinPoint pjp) {
System.out.println("配置环绕通知:TransactionManager切入点和通知");
Object rtValue = null;
try {
Object[] args = pjp.getArgs();//得到方法执行所需的参数
beginTransaction();
rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)
commitTransaction();
return rtValue;
} catch (Throwable t) {
rollbackTransaction();
throw new RuntimeException(t);
} finally {
closeTransaction();
}
}
}
/*
这些就是xml配置内容,这个类就是替代bean.xml,从而不需要bean.xml文件
用
@Configuration-->告诉spring这个就是等价Bean.xml文件
@ComponentScan
等价下面的
<context:component-scan base-package="com.sise"/>
用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。
下面将创建一个类JdbcConfig ,实现下面代码的替换
从而用@bean存再spring容器中,就等价 <bean id="" class="">
*
* <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="DBCPdataSource"></property>
</bean>
*
*
* <!-- 配置DBCP数据源 -->
<bean id="DBCPdataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///ssm"></property>
<property name="username" value="root"></property>
<property name="password" value="8438031100"></property>
</bean>
*
* */
/**
* 该类是一个配置类,它的作用和bean.xml是一样的
* spring中的新注解
* Configuration
* 作用:指定当前类是一个配置类
* 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
* ComponentScan
* 作用:用于通过注解指定spring在创建容器时要扫描的包
* 属性:
* value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
* 我们使用此注解就等同于在xml中配置了:
* <context:component-scan base-package="com.itheima"></context:component-scan>
* Bean
* 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
* 属性:
* name:用于指定bean的id。当不写时,默认值是当前方法的名称
* 细节:
* 当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
* 查找的方式和Autowired注解的作用是一样的
* Import
* 作用:用于导入其他的配置类
* 属性:
* value:用于指定其他配置类的字节码。
* 当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
* PropertySource
* 作用:用于指定properties文件的位置
* 属性:
* value:指定文件的名称和路径。
* 关键字:classpath,表示类路径下
*/
@Configuration
@ComponentScan(basePackages = "com.sise")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbc.properties")
/*
用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。*/
public class SpringConfiguration {
}
/*
这些就是xml配置内容,这个类就是替代bean.xml,从而不需要bean.xml文件
用
@Configuration-->告诉spring这个就是等价Bean.xml文件
@ComponentScan
等价下面的
<context:component-scan base-package="com.sise"/>
用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。
下面将创建一个类JdbcConfig ,实现下面代码的替换
从而用@bean存再spring容器中,就等价 <bean id="" class="">
*
* <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="DBCPdataSource"></property>
</bean>
*
*
* <!-- 配置DBCP数据源 -->
<bean id="DBCPdataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///ssm"></property>
<property name="username" value="root"></property>
<property name="password" value="8438031100"></property>
</bean>
*
* */
/**
* 该类是一个配置类,它的作用和bean.xml是一样的
* spring中的新注解
* Configuration
* 作用:指定当前类是一个配置类
* 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
* ComponentScan
* 作用:用于通过注解指定spring在创建容器时要扫描的包
* 属性:
* value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
* 我们使用此注解就等同于在xml中配置了:
* <context:component-scan base-package="com.itheima"></context:component-scan>
* Bean
* 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
* 属性:
* name:用于指定bean的id。当不写时,默认值是当前方法的名称
* 细节:
* 当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
* 查找的方式和Autowired注解的作用是一样的
* Import
* 作用:用于导入其他的配置类
* 属性:
* value:用于指定其他配置类的字节码。
* 当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
* PropertySource
* 作用:用于指定properties文件的位置
* 属性:
* value:指定文件的名称和路径。
* 关键字:classpath,表示类路径下
*/
@Configuration
@ComponentScan(basePackages = "com.sise")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbc.properties")
/*
用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。*/
public class SpringConfiguration {
}
<context:component-scan base-package="com.sise"/>
<!--配置QueryRunner-->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<!-- 如果用QueryRunner封装数据库模板据库需要用构造函数引入数据源
如果用JdbcTemplate
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="DBCPdataSource"></property>
</bean>
就不需要用构造函数
-->
<!--注入数据源-->
<constructor-arg name="ds" ref="DBCPdataSource"></constructor-arg>
<!-- 如果想线程和连接绑定,则需要再daoImpl里面的sql语句前面添加connectionUtils.getThreadConnection(),
return runner.query(connectionUtils.getThreadConnection(),"select * from mybatisacount"
, new BeanListHandler<AcountBean>(AcountBean.class));
而且要注掉这个1语句:<constructor-arg name="ds" ref="dataSource"></constructor-arg>
这个语句不注掉,就会创建多个连接,使事务不能使用
-->
<!-- <property name="runner" ref="runner"></property> 用这个就会出现错误-->
</bean>
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="DBCPdataSource"></property>
</bean>
<!-- 配置c3p0数据源 -->
<bean id="c3p0dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--连接数据库的必备信息-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm"></property>
<property name="user" value="root"></property>
<property name="password" value="8438031100"></property>
</bean>
<!-- 配置Spring内置数据源 -->
<bean id="SpringDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"></property>
<property name="username" value="root"></property>
<property name="password" value="8438031100"></property>
</bean>
<!-- 配置DBCP数据源 -->
<bean id="DBCPdataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///ssm"></property>
<property name="username" value="root"></property>
<property name="password" value="8438031100"></property>
</bean>
<!-- 如果用QueryRunner封装数据库模板据库需要用构造函数引入数据源
如果用JdbcTemplate
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="DBCPdataSource"></property>
</bean>
就不需要用构造函数
-->
<!--注入数据源-->
<constructor-arg name="ds" ref="DBCPdataSource"></constructor-arg>
<!-- 如果想线程和连接绑定,则需要再daoImpl里面的sql语句前面添加connectionUtils.getThreadConnection(),
return runner.query(connectionUtils.getThreadConnection(),"select * from mybatisacount"
, new BeanListHandler<AcountBean>(AcountBean.class));
而且要注掉这个1语句:<constructor-arg name="ds" ref="dataSource"></constructor-arg>
这个语句不注掉,就会创建多个连接,使事务不能使用
-->
<!-- <property name="runner" ref="runner"></property> 用这个就会出现错误-->
</bean>
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="DBCPdataSource"></property>
</bean>
<!-- 配置c3p0数据源 -->
<bean id="c3p0dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--连接数据库的必备信息-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm"></property>
<property name="user" value="root"></property>
<property name="password" value="8438031100"></property>
</bean>
<!-- 配置Spring内置数据源 -->
<bean id="SpringDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"></property>
<property name="username" value="root"></property>
<property name="password" value="8438031100"></property>
</bean>
<!-- 配置DBCP数据源 -->
<bean id="DBCPdataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///ssm"></property>
<property name="username" value="root"></property>
<property name="password" value="8438031100"></property>
</bean>
版权声明:未标注转载均为本站原创,转载时请以链接形式注明文章出处。如有侵权、不妥之处,请联系站长删除。敬请谅解!
常见资源合集和破解 fmvvvteih...