Spring
什么是框架(半成品软件)
高度抽取可重用代码的一种,高度的通用性; 多个可重用模块的集合,形成一个某个领域的整体解决方案.
Spring
是一个java企业级应用的开源开发框架
Spring的好处:
1.轻量级
2.非侵入式(不依赖Spring中的API,不用知道其方法)
3.容器(可以管理所有的组件(类))框架
4.控制反转(IOC:Spring通过控制反转实现松散耦合,对象们给出他们的依赖,而不是创建或查找依赖的对象们)
5.面向切面的编程(AOP:Spring支持面向切面的编程,将应用业务逻辑和系统服务分开)
6.MVC框架
7.事务管理:Spring提供一个事务管理接口,可以扩展到上至本地事务下至全局事务.
8.异常处理:Spring提供方便的API把具体技术相关的异常(JDBC)转化为一致的unchecked异常.
***核心关注: IOC(依赖注入)和AOP(面向切面编程)***
Spring框架模块:
Test:Spring的单元测设模块
Core Container: 核心容器(IOC); 由Beans, Core,Context,SpEL这些jar包组成,这些jar包都得导入
AOP+Aspect模块:面向切面编程模块
Data Access/Intergration:(数据访问/集成)Spring访问数据库模块:由JDBC,ORM(Object relation Mapping) ,OXM(X:xml),JMS,Transaction(TX:事务)
Web:Spring开发Web应用模块(Web-Servlet, Web-Struts, Web-Portlet)
IOC:(Inversion(反转) of Control):控制反转
控制:控制资源的获取方式
主动式: 要什么资源,就自己创建(复杂对象创建是庞大的工程)
被动式:资源的获取不是我们创建,而是交给容器创建和设置
容器:管理所有的组件(有功能的类)
容器相当于(婚介所);
主动获取资源变为被动接收.
D I (Dependency Injection):依赖注入
容器能知道那个组件(类)运行的时候,需要另外一个类,容器通过反射的形式,将容器中准备好的对象(通过反射给属性赋值)注入到类中.
只要是容器管理的组件,都能使用容器提供的强大功能;
Spring中的依赖注入:
Dependency Injection: (DI)
IOC的作用: 降低程序间的耦合
依赖关系的管理:
都交给Spring来维护
在当前类中需要调用其它类的对象,由spring提供,只需在配置文件中说明 依赖注入的数据类型:
基本类型和String
其他bean类型
复杂类型和集合类型
注入的方式:
1.构造函数注入:
使用的标签:constructor-arg 出现在bean标签的内部
标签中的属性:
type:用于指定要注入的数据的数据类型
index:用于指定要注入的数据给构造函数中指定位置的参数赋值
name:用于给构造函数中指定名称的参数赋值 (常用)
value:用于提供基本类型和String类型的数据
ref: 用于指定其他的bean类型数据,就是在spring中出现的bean对象
<bean id =? class=?>
<constructor-arg name="name" value="test">
<constructor-arg name="age" value="18">
<constructor-arg name="birthday" ref="now">
</bean>
配置一个日期对象
<bean id="now" class="java.util.Date"> </bean>
优势:在获取bean对象时,注入数据是必须的操作,否则无法成功
劣势:改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供
2.使用set方法注入 更常用
涉及的标签:property bean标签的内部
标签的属性:
name:用于指定注入时使用的set方法名称
value:用于提供基本类型和String类型的数据
ref: 用于指定其他的bean类型数据,就是在spring中出现的bean对象
<bean id =? class=?>
<property name="name(小写) value="Test"> </property>
<property name="age(小写) value="21"> </property>
<property ="birthday(小写) ref="now"> </property>
</bean>
优势:创建对象时没有明确的限制,可以直接使用默认构造函数
劣势:如果有某个成员必须有值,则获取对象时有可能set方法没有执行
复杂类型的注入/集合类型的注入:
用于给List结构集合注入的标签:
list, array, set
用于给Map结构集合注入的标签:
map, props
结构相同,标签可以互换
3.使用注解的方式
注解: (使用注解时,要告知spring在创建容器时要扫描的包,配置所需的标签不是在beans中,而是context中)
<context:component-scan base-package=" ?"> </context:component-scan>
1.用于创建对象的
作用就和xml配置文件中编写<bean>标签实现的功能是一样的
@Component: 把当前类对象存入Spring容器中
属性: value : 用于指定bean的id(不写value,默认值为当前类名的首字母小写)
@Controller: 用于表现层
@Service: 用于业务层
@Repository: 用于持久层
以上三个注解的作用和属性与Component是一模一样,它们三个是spring框架为我们提供的三层使用的注解,使我们的三层对象更加清晰
2.用于注入数据的
作用就和xml配置文件中的bean标签中写一个<property>标签一样
@Autowired: 自动按照类型注入,只要容器中有唯一一个bean对象类型和要注入的变量类型匹配,可以注入成功
出现位置:可以是成员变量上,也可以是方法上.
@Qualifer:再按照类注入的基础上再按照名称注入,他在给类成员注入时不能单独使用(需要和Autowired一块使用),但是再给方法参数注入时可以
属性: value用于指定注入bean的id
@Resource:直接按照bean的id注入,可以单独使用
属性: name 用于指定bean的id
以上三个注解都只能注入其他bean类型的数据,其他基本类型和String无法通过上述注解,集合类型的注入只能通过xml实现
@Value: 用于注入基本类型和String类型的数据
属性: value 用于指定数据的值 ,可以使用spring中SpEl(spring中的表达式)
SpEl的写法: ${表达式}
3.用于改变作用范围的
作用就和xml配置文件中bean标签中 scope的作用一样
@Scope: 用于指定的bean的范围 (在类上面添加)
属性: value 常用值:singleton ,prototype
4.和生命周期相关 (了解)
作用就和xml配置文件中bean标签中init-method 和 destory-method作用一样
@PreDestory: 用于指定销毁方法
@PostConstruct: 用于指定初始化方法
5.Spring中的新注解
@Configuration:
作用:表示当前类是一个配置类
细节:当配置类作为AnnotationConfigApplicationContext的参数时,该注解可以不写
@ComponentScan:
作用:用于通过注解指定spring在创建容器时扫描的包
相当于 <context:component-scan base-package="com.tulun"></context:component-scan>* @Bean:
作用:把当前方法的返回值作为bean对象 ,存入spring的ioc容器中
属性:
name :指定bean的id 默认值为当前方法的名称
当使用注解配置时,如果方法有参数,spring框架会去容器中查找是否有可用的bean对象
查找的方式和 Autowired注解的作用一样
@Import:
作用:导入其他的配置类
属性:
value:用于指定其他配置类的字节码
当使用Import注解后,有Import注解的类就是主配置类,导入的都为子配置类
@PropertySource:
作用:用于指定properties文件的位置
属性:value :指定文件的名称和路径 classpath:表示类路径下
--------核心容器的两个接口引发出的问题--------
ApplicationContext: 单例对象适用 实际开发采用此接口
它在构建核心容器时,创建对象采取的策略是立即加载的方法,也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象.
BeanFactory: 多例对象适用
它在构建核心容器时,创建对象的策略是采用延迟加载的方式,也就是说,什么时候根据id获取对象了,什么时候才创建对象.
Spring对Bean的管理细节
1.创建Bean的三种方式
1).通过默认构造函数创建
<bean id ="?" class="?"> </bean>
2).使用某个类中方法创建对象
<bean id="?" factory-bean="?" factory-method="?"> </bean>
3).使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象)
<bean id="?" class=? factory-method=?> </bean>
2.bean对象的作用范围
bean标签的scope属性
取值: singleton:单例(默认值)
prototype:多例
request:作用于web应用的请求范围
session:作用于web应用的会话范围
global-session:作用于集群环境的会话范围(全局会话范围),非集群环境,就是 session.
3.bean对象的生命周期
单例对象: 单例对象的生命周期与容器共存亡
出生:当容器创建时对象出生
活着:容器还在,对象一直活着
死亡:容器销毁,对象死亡
多例对象:
出生:当使用对象时 创建对象
活着:对象在使用过程中,就一直活着
死亡:当对象长时间不用且长时间没有别的对象引用时.
什么是AOP:
AOP:面向切面编程,在程序开发中解决系统层面上的问题,比如日志,事务,权限等.
在不改变原有的逻辑的基础上,增加一些额外的功能.
AOP可以说是OOP的补充和完善,允许定义纵向的关系,在设计中导致了大量代码的重复,不利于各个模块的重用.而AOP恰恰相反,它利用一种称为"横切"的技术,将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面:就是与哪些业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,有利于未来的可操作性和可维护性.
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点.业务处理的主要流程是核心关注点. 横切关注点的一个特点是它们经常发生在核心关注点的多处,而各处基本相似,如权限认证,日志,事务.AOP主要将核心关注点和横切关注点分离开来.
AOP的相关概念:
spring中的AOP相关术语
横切关注点:
对那些方法进行拦截,拦截后怎么处理,这些关注点成为横切关注点
Joinpoint(连接点):
所谓连接点就是那些被拦截的点,spring中这些点指的是方法 (业务层的方法)
Pointout(切入点):
所谓切入点就是指我们要对那些Joinpoint进行拦截的定义(对业务层的方法增强,若没有增强,则不是切入点)
Advice(通知/增强):
所谓通知是指拦截到Joinpoint后要做的事情就是通知. 有前置通知,后置通知,环绕通知,异常通知,最终通知
Introduction(引介);
引介是一种特殊的通知在不修改类代码的前提下,引介可以在运行期为类动态的添加方法或Field
Target(目标对象):
代理的目标对象
Waving(织入):
是指把增强应用到目标对象来创建新的代理对象的过程
Proxy(代理):
一个类被AOP织入增强后,就产生一个代理类 ,可以是JDK动态代理,也可以是cglib代理.
Aspect(切面):
是切入点和通知(引介)的结合
Advice通知类型介绍:
before:在目标方法调用之前做增强处理
AfterReturning:在目标方法正常完成后做增强
AfterThrowing:主要用来处理程序中未处理的异常
After:在目标方法完成之后做增强,无论目标方法是否成功完成
Around:环绕通知.在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志都是环绕通知,核心是一个ProceedingJoinPoint.
AOP使用场景:
Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 懒加载
Debugging 调试
logging, tracing ,profiling and monitoring 记录追踪 优化 校准
Performance optimization 性能优化
Persistence 持久化
Resource pooling 资源池
Synchronization 同步
Transaction 事务
spring中基于XML和注解的AOP配置
xml配置AOP主要代码:
Bean:
<!--Spring中基于xml的AOP配置
1.吧通知Bean也交给Spring管理
2.使用aop:config标签开始AOP配置
3.使用aop:aspect表示开始配置切面
id属性:是给切面提供一个唯一标识
ref属性:指定通知类Bean的id
4.在aop:aspect的内部使用对应标签来配置通知的类型
示例:让printLog方法在切入点方法执行之前执行,所以为前置通知,
aop:before 前置通知
method的属性: 用于指定Logger类中那个方法是前置通知
5.pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层哪些方法增强
切入点表达式的写法
关键字:execution(表达式)
表达式:
访问修饰符 返回值 包名-包名...类名.方法名(参数列表)
标注写法:
execution(public void com.tulun.impl.UserServiceImpl.findAllUser())
访问修饰符可以省略:
execution( void com.tulun.impl.UserServiceImpl.findAllUser())
返回值可以使用通配符,表示任意返回值
execution(* com.tulun.impl.UserServiceImpl.findAllUser())
包名可以使用通配符,表示任意包,但是有几级包,就得写几个*
execution(* *.*.*.
UserServiceImpl. findAllUser()) 包名可以使用.. 表示当前包及其子包
execution(* *..
UserServiceImpl. findAllUser()) 类名和方法名都可以使用*进行通配
execution(* *..*.*() )
参数列表:
基本类型直接写名称 int
引用类型,写包名.类名的方式 java.lang.String
可以使用通配符 * 表示任意参数
可以使用 .. 表示有无参数都可以
全通配符写法:
* *..*.*(..)
实际开发中切入点表达式的通常写法:
切到业务层实现类下的所有方法:
* com.tulun.service.impl.*.*(..)
-->
<!--配置Spring中的IOC ,吧service对象配置进来-->
<bean id="userService" class="com.tulun.impl.UserServiceImpl"></bean>
<!--配置Logger类-->
<bean id="logger" class="com.tulun.utils.Logger"></bean>
<!--配置AOP-->
<aop:config>
<!--配置切面 比如程序中需要增加日志功能,日志就是切面-->
<aop:aspect id="logAdvice" ref="logger">
<!--配置通知的类型,并且建立通知的方法和切入点之间的关联-->
<!--前置通知,在切入点方法执行之前执行-->
<aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>
<!--后置通知,在切入点方法正常执行之后执行 ,他和异常通知永远只能执行一个-->
<aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>
<!--异常通知,在切入点方法产生异常后执行 ,他和后置通知永远只能执行一个-->
<aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>
<!--最终通知,无论怎眼都会执行-->
<aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>
<!--配置切入点表达式 id属性 用于指定表达式的唯一标志 expression用于指定表达式内容-->
<aop:pointcut id="pt1" expression="execution(public void com.tulun.impl.UserServiceImpl.findAllUser())"/>
<!---配置环绕通知 ,详细的注释请看Logger内部-->
<aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>
</aop:aspect>
</aop:config>
需要的依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
</dependencies>
注解配置AOP主要代码:
xml文件:
<!--配置Spring容器创建时要扫描的包-->
<context:component-scan base-package="com.tulun"></context:component-scan>
可以用@ComponentScan(basepackage="?")替换
<!--配置Spring开启注解AOP的支持 写上就支持,没写就不支持-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
可以用@EnableAspectAutoProxyt替换
相关类:
@Service("userService")
public class UserServiceImpl implements IUserService {
}
@Component("logger")
@Aspect //表示当前类是一个切面类
public class Logger {
//切点表达式
@Pointcut("execution(* com.tulun.impl.*.*(..))")
private void pt1() {
}
//通知类型
/**
* 前置通知
*/
@Before("pt1()")
public void beforePrintLog() {
System.out.println("前置通知:Logger中的方法beforePrintLog开始记录日志了...");
}
/**
* 后置通知
*/
@AfterReturning("pt1()")
public void afterReturningPrintLog() {
System.out.println("后置通知:Logger中的方法afterReturningPrintLog开始记录日志了...");
}
/**
* 异常通知
*/
@AfterThrowing("pt1()")
public void afterThrowingPrintLog() {
System.out.println("异常通知:Logger中的方法afterThrowingPrintLog开始记录日志了...");
}
/**
* 最终通知
*/
@After("pt1()")
public void afterPrintLog() {
System.out.println("最终通知:Logger中的方法finalPrintLog开始记录日志了...");
}
/**
* 环绕通知
* 问题: 业务层的打印和通知 到底那个打印了
* 当配置了环绕通知后,切入点方法没有执行,而通知方法执行了
* 分析:
* 通过对比动态代理中的环绕通知代码,发现动态代理中的环绕通知有明确的业务层切入点调用
* 解决:
* spring框架为我们提供了一个接口,ProceedJoinPoint 该接口有个方法 proceed()该方法就相当于明确调用切入点方法
* 该接口可以作为环绕通知的方法参数,程序执行时,spring会为我们提供该接口的实现类,供我们使用
*
* spring中的环绕通知
* 它是spring框架为我们提供的一种可以在代码手动控制增强方法何时执行的方式
*/
@Around("pt1()")
public Object aroundPrintLog(ProceedingJoinPoint pjp) {
Object rtValue = null;
try {
System.out.println("Logger中的方法aroundPrintLog开始记录日志了...前置");
Object[] args = pjp.getArgs(); //得到方法执行所需的参数
rtValue = pjp.proceed(args); //明确调用业务层切入点方法
System.out.println("Logger中的方法aroundPrintLog开始记录日志了...后置");
return rtValue;
} catch (Throwable throwable) {
System.out.println("Logger中的方法aroundPrintLog开始记录日志了...异常");
throw new RuntimeException(throwable);
} finally {
System.out.println("Logger中的方法aroundPrintLog开始记录日志了...最终");
}
}
spring中的事务控制
spring中事务控制的一组API:
PlatformTransactionManager 接口:
DataSourceTransactionManager 实现类
基于xml:
<!--配置账户的业务层-->
<bean id="accountService" class="com.tulun.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!--配置账户的持久层-->
<bean id="accountDao" class="com.tulun.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置dataSource数据源-->
<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:3306/test"></property>
<property name="username" value="debian-sys-maint"></property>
<property name="password" value="YN6bICN3ccV5FbIn"></property>
</bean>
<!-- 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>
<!-- 配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事务的属性
isolation:指定事务的隔离级别 默认值为DEFAULT,表示使用数据库的默认隔离级别
propagation:用于指定事务的传播行为 默认为REQUIRED,表示一定会有事务 ,增删改的选择 .查询方法可以选择 SUPPORT
read-only:用于指定事务是否只读 只有查询方法才能设置为只读 默认值为false ,表示读写
timeout:指定事务的超时时间 ,默认值是-1,表示永不超时 ,如果指定了数值,以秒为单位
no-rollback-for:但产生该异常时,事务不回滚,反之则回滚. 没有默认值,表示任何异常都回滚
rollback-for: 用于指定一个异常,产生该异常时,事务回滚,产生其他异常时,事务不回滚, 没有默认值,表示任何异常都回滚
-->
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--配置aop-->
<aop:config>
<!--配置切入点表达式-->
<aop:pointcut id="pt" expression="execution(* com.tulun.service.impl.*.*(..))"/>
<!--建立切入点表达式和事务通知之间的关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
基于注解:
spring中的JDBC Template
1.JDBCTemplate的作用
用于和数据库交互,实现对表的CRUD操作
JDBCTemplate代码实现:
最基本实现:
//准备数据源:spring内置数据源
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("debian-sys-maint");
dataSource.setPassword("YN6bICN3ccV5FbIn");
//1.创建对象
JdbcTemplate jt = new JdbcTemplate();
//2.jt设置数据源
jt.setDataSource(dataSource);
//3.执行操作
jt.execute("insert into account(id,banlance)values(3,1000)");
配置方式:
jdbcTemplate的xml配置方法:
<!--配置jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置dataSource数据源-->
<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:3306/test"></property>
<property name="username" value="debian-sys-maint"></property>
<property name="password" value="YN6bICN3ccV5FbIn"></property>
</bean>
<!--配置账户的持久层 方法1-->
<bean id="accountDao" class="com.tulun.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!--配置账户的持久层 方法2-->
<bean id="accountDao" class="com.tulun.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
账户的持久层继承该类,该类的内部方法:
使用该方法后,不用在持久层dao的实现类中创建JdbcTemplate对象,只需要在xml文件accountDao注入dataSource,注入之后这个类内部会调用createJdbcTemplate自动创建JdbcTemplate属性,可以用getJdbcTemplate()方法获取
JdbcTemplate对象
//与上面方法2同用
public class AccountDaoImpl extends
JdbcDaoSupport implements IAccountDao {}
例如: getJdbcTemplate().query()
JdbcDaoSupport内部主要方法:
public void setDataSource(DataSource dataSource) {
if(jdbcTemplate == null) {
jdbcTemplate = createJdbcTemplate(dataSource);
}
}
private JdbcTemplate createJdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(
dataSource);
}
jdbcTemplate的纯注解配置方法:
@Repository
public class AccountDaoImpl implements IAccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
//和数据库连接相关的配置类
public class JdbcConfig {
@Value("${driver}")
private String driver;
@Value("${url}")
private String url;
@Value("${username}")
private String username;
@Value("${password}")
private String password;
@Bean(name = "jdbcTemplate")
public JdbcTemplate createJdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name = "dataSource")
public DataSource createDataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
//jdbcConfig.properties文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=debian-sys-maint
password=YN6bICN3ccV5FbIn
获取容器的方法:
ApplicationContext ac = new AnnotationConfigApplicationContext(jdbcConfig.class);
JdbcTemplate的CRUD操作:
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.获取对象
JdbcTemplate jt = (JdbcTemplate)ac.getBean("jdbcTemplate",JdbcTemplate.class);
//3.执行操作 单表操作
//插入操作
jt.execute("insert into account(id,banlance)values(4,500)");
//保存操作
jt.update("insert into account(id,banlance)values(?,?)",5,333);
//更新操作
jt.update("update account set banlance=? where id=?",222,5);
//删除操作
jt.update("delete from account where id=?",5);
//查询所有
List<Account> query = jt.query("select *from account where banlance>?", new AccountRowMapper(), 1000);
//Spring提供的
List<Account> query = jt.query("select *from account where banlance>?", new BeanPropertyRowMapper<Account>(Account.class), 500);
for(Account account: query) {
System.out.println(account);
}
//查询一个
List<Account> query = jt.query("select *from account where id=?", new AccountRowMapper(), 2);
System.out.println(query.get(0));
//查询返回一行一列(使用聚合函数,但不加group by)
Long aLong = jt.queryForObject("select count(*) from account where banlance >?", Long.class, 100);
System.out.println(aLong);
/**
* Account的封装策略
*/
class AccountRowMapper implements RowMapper {
/**
* 把结果集的数据封装到Account中,由spring吧每个Account添加到集合中
* @param resultSet
* @param i
* @return
* @throws SQLException
*/
public Object mapRow(ResultSet resultSet, int i) throws SQLException {
Account account = new Account();
account.setId(resultSet.getInt("id"));
account.setMoney(resultSet.getDouble("banlance"));
return account;
}
}