Spring IOC,AOP,事务和JDBC Template操作

Spring框架详解(持续更新) Mybatis Spring SpringMVC详解 阅读详情

什么是框架(半成品软件)

高度抽取可重用代码的一种,高度的通用性; 多个可重用模块的集合,形成一个某个领域的整体解决方案.

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;
    }
}
SARscape的DInSAR全流程-以西安市隋大兴唐长安城遗址为例 通过DInSAR对西安市隋大兴唐长安城遗址开展的年度周期性监测,发现成因是地质内部构造断裂带活动所导致的地面产生物理空间上的形变,而地面的沉降与抬升是直接影响城市发展与文化遗产保护最为常见的缓变型不可逆地质灾害。西安市地处汾渭断陷盆地中部,受临潼-长安断裂带影响,导致区域内构造活动较为强烈。由于早年西安市地表水资源匮乏,从上世纪50年代末开始大量开采地下水资源以满足城市人口不断扩张的需求,从而导致地下承压含水层水位急速下降,形成多个局部沉降中心(八里村、西工大、电子城等)。 阅读详情

相关推荐

CUDA系列-Stream-1

This section describes static aspects of the CUSW_UNIT_STREAM unit’s architecture.和stream相关的其它Unit主要有Channel,Sync,Memmgr A CUDA stream is a software FIFO queue that allows commands like kernel launch and memcpy to be enqueued in it. The enqueued commands

weixin_43360707的博客 734

spring框架--全面详解(学习笔记)

由 Spring IoC 容器管理的对象称为 Bean,Bean 根据 Spring 配置文件中的信息创建。可以把 Spring IoC 容器看作是一个大工厂,Bean 相当于工厂的产品,如果希望这个大工厂生产和管理 Bean,则需要告诉容器需要哪些 Bean,以及需要哪种方式装配 Bean。Spring 配置文件支持两种格式,即 XML 文件格式和 Properties 文件格式。

swy2560666141的博客 1万+

实战对比:VINS和ORBSLAM3在无人机避障中的表现(含实测数据)

本文通过实战测试,深度对比了VINS和ORBSLAM3两种主流视觉SLAM算法在无人机避障中的表现。测试聚焦于光照变化、动态遮挡和快速运动三大挑战,提供了详细的实测数据与性能分析。结果表明,VINS在计算效率和实时性上占优,而ORBSLAM3在定位精度和地图管理方面更稳健,为不同应用场景下的工程选型提供了清晰依据。

醉三国 627

Spring框架详解

1.Spring框架是轻量级的JavaEE框架2.Spring可以解决企业应用开发的复杂性3.Spring有两个核心部分IOC和Aop(1)IOC控制反转,把创建对象的过程交给Spring进行管理(2)Aop面向切面,不修改源代码进行功能增强4.Spring特点(1)方便解耦,简化开发(2)Aop变成支持(3)方便程序测试(4)方便和其他框架进行整合(5)方便进行事物操作(6)降低API开发难度5.Spring5one控制反转,把对象的创建和对象的调用过程交给Spring进行管理。...

m0_54853420的博客 2376

医学影像AI的幻觉问题与CCD解决方案

医学影像AI在辅助诊断中面临的核心挑战是幻觉现象,即模型生成不符合实际影像的虚假诊断。这种现象源于多模态大语言模型(MLLMs)在视觉-语言对齐上的技术局限,可能导致假阳性或假阴性的临床风险。通过临床对比解码(CCD)框架,结合症状锚定和专家引导的双阶段校准机制,可有效提升模型输出的可靠性。该技术在CheXpert和MIMIC-CXR等标准数据集上验证,显著改善了肺不张、胸腔积液等关键指标的检测准确率。对于医疗AI落地场景,这种即插即用的解决方案既规避了数据隐私合规问题,又降低了基层医院的部署门槛,为AI辅

weixin_36303807的博客 322

DeepSeek研发的精算大模型「精卫」已实现98%精算任务覆盖,中国人寿采用后年节约3.2亿元技术采购成本,形成关键技术替代效应

根据现有资料,精算领域关键技术替代效应的行业标准定义尚未明确具体提及。然而,可以从相关文献中提取一些关键概念和方法来推导出可能的定义。​替代效应的基本定义​:替代效应是指一种商品价格变动引起另一种商品的相对价格变动,从而导致消费者在维持原有效用水平不变的条件下对商品需求量做出的调整。​技术替代效应​:在精算领域,技术替代效应可以理解为新技术或新方法对现有技术或方法的替代,从而影响精算模型、数据处理和决策过程。例如,机器学习在精算中的应用日益增长,改变了精算师的工作方式和模型构建方法。​。

百态·数智思维 | 聚焦大数据、量化与未来AI 1712

Spring框架

spring框架:负责宏观调控,负责整合其他的第三方的框架 IOC介绍 IOC是一种控制反转的设计思想,由spring容器管理对象的生命周期,降低代码的耦合性。 将所有的对象都交给spring容器管理,容器负责对象的注入 DI介绍:Dependency Injection 依赖注入 spring容器替你管理一系列需要的类,前提是你需要将这些类表示交给容器进行管理才可,然后在你需要的时候不用自己去定义,容器就会自动帮你进行实例化 实现IOC思想需要DI进行注入。 注入的方式最常用的就是@A...

Mr_Jin的博客 4665

Cartographer从安装到实战:手把手教你运行2D/3D建图与定位

本文提供了一份详尽的Cartographer从零安装到实战应用的完整指南。内容涵盖环境准备、依赖编译、源码构建等关键步骤,并手把手指导读者运行2D/3D官方数据集进行建图与定位测试。文章深入解析了参数配置与自定义数据适配方法,帮助开发者快速掌握这一强大的实时同步定位与建图工具,并将其应用于机器人导航与自动驾驶等实际场景。

rice5的博客 952

Spring5

Spring框架概述 Spring5是轻量级的开源的javaEE框架 使用基本的JavaBean代替EJB,解决企业应用开发的复杂性 Spring有两个核心部分:IOC和AOP IOC(Inversion of Control 即控制反转)将对象交给容器管理,把创建对象的过程交给Spring进行管理 AOP (Aspect Orient Programming),直译过来就是 面向切面编程,AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。不修改源代码的情况下,进行功能的增强 Spri

ljz66254的博客 173

FPGA实战:基于Basys3的多功能数字钟设计与实现

本文详细介绍了基于Basys3开发板的多功能数字钟设计与实现过程,涵盖FPGA开发、SystemVerilog编程及7段数码管驱动等关键技术。通过模块化设计实现时钟分频、时间计数、按键处理等功能,并提供了优化显示驱动和调试技巧,帮助开发者快速掌握数字电路设计核心概念。

weixin_29186249的博客 659

英飞凌 AURIX TC3XX 系列单片机的链接文件

这篇介绍英飞凌 AURIX TC3XX 系列单片机的链接文件,主要是针对使用 SOTA 功能如何修改链接文件,完整地实现 SOTA 功能

大橙子的博客 4385

第21~22周Java主流框架入门-Spring 3.SpringJDBC事务管理

Spring JDBC模块及核心对象JDBC Template的使用通过学习如何使用Spring JDBC模块,了解JDBC Template的CRUD操作,并探索如何简化数据库操作。声明式事务的配置方式学习如何在Spring中进行声明式事务的配置,以实现对事务的自动管理。事务传播行为的配置探讨在Spring事务管理中如何配置事务的传播行为,以应对不同的业务场景。提供了对JDBC的轻量封装,简化了数据库操作,并通过IOC容器增强了代码的可管理性。事务管理。

Sweeping_Robot的博客 1212

使用 Prometheus 监控 Spring Boot 应用

本文介绍了使用SpringBoot+Prometheus+Grafana实现应用监控的方案。首先在SpringBoot项目中集成Micrometer和Actuator组件,通过配置暴露Prometheus监控端点。接着配置Prometheus采集应用指标数据,并通过Grafana可视化展示。具体步骤包括:1)SpringBoot集成Micrometer;2)配置Prometheus抓取应用指标;3)安装Grafana并导入SpringBoot监控模板;4)展示JVM和业务指标。该方案可以实现对SpringB

蔡定努 431

SpringIOC/AOP/事务管理

SpringIOC/AOP/事务管理学习笔记,方便后期查阅。

spark2010的博客 849

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Spring笔记IOC AOP JDBC Template

学习Spring的相关笔记,还没完全学完,感觉上要点就这么多吧,主要就是配置。 IOC: ApplicationContext (IOC容器的接口) ClassPathXmlApplicationContext ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml"); 同一个组件在IOC中是单实例的 p名称空间:XML配置文件下面namespace 勾选 p:age="14"直接写到bean标签里 复杂赋值,都在标签体中 &

weixin_43808401的博客 200

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Spring

Spring1.Spring是什么?有什么好处?2.IOC是什么?有什么好处?具体过程?3.DI是什么?4.IOC和DI的关系?5.bean标签的属性有哪些?6.IOC创建对象有哪几种方式?7.Spring是如何实现IOC的?也就是如何创建对象的? 1.Spring是什么?有什么好处? 概念: SPring是一个支持控制反转(IOC)和面向切面编程(AOP)的容器框架。 好处: 两降低>&...

weixin_43766298的博客 1万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Spring5全部笔记--IOC、AOP、JdbcTemplate、事务、新特性

1、什么是IOC(1)控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理(2)使用IOC目的:为了耦合度降低(3)做入门案例就是IOC实现2、IOC底层原理(1)xml解析、工厂模式(一种设计模式)、反射3、讲解IOC底层原理IOC过程1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂2、Spring 提供IOC容器事项两种方式:(两个接口)3、 接口有实现类1、什么是 Bean 管理2、Bean 管理操作有两种方式1、基于 xml 方式创建对象2、基于 xml 方式注入属性3、第

qq_45872633的博客 252

Spring学习笔记

Spring 学习笔记 IOC 和 DI 的概述 IOC(Inversion of Controll) DI(Dependency Injection) Spring配置 ApplicationContext Bean的相关配置 bean标签的id和name的配置 bean的生命周期的配置 bean的作用范围的配置 Spring的Bean管理配置 Spring的Bean的实例化方...

weixin_42135811的博客 1597

spring事务管理实现原理-源码篇

引用场景 就是这两个方法,第一个方法中引用了第二个方法,都用@Transactional注解。debug调用shopping方法,这就是我们平时使用声明式事务进行处理的(也可以用编程式)但是原理是什么呢?又是如何关联到JDBC的事务管理呢?接下来大家带着这两个问题出发: 引子 在Spring中,事务有两种实现方式: 编程式事务管理: 编程式事务管理使用TransactionTemplate可实现更细粒度的事务控制。 申明式事务管理: 基于Spring AOP实现。其本质是对方法前后进行拦截,然.

lucky_love816的博客 1178

Spring整理

1 Spring基本介绍 1.1 一图胜千言 1.2 Spring原生容器底层结构 2 Spring管理bean-IOC 2.1 基于XML来配置bean 2.2 基于注解配置bean 3 AOP 3.1 JDK动态代理 3.2 AOP基本介绍 3.3 AOP快速入门 3.4 AOP切入表达式 3.5 AOPJonintPoint 3.6 AOP返回通知获取结果 3.7 AOP异常通知获取异常 3.8 AOP环绕通知 3.9 AOP切入表达式重用 3.10 AOP切面优先级问

weixin_57208934的博客 764

(2020)Spring框架(基础和中级部分)

2020 Spring框架 一、框架的概述 1、spring是什么?为了解决什么提出的? Spring是一个轻量级Java开发框架,目的是为了解决企业级应用开发的业务逻辑和其它层的耦合问题(简化java开发) spring可以做很多东西,为企业级平台提供了丰富的功能,但是这些功能的都依赖与他的两个核心特性,控制反转和面向切面编程 2、Spring的优点(减低耦合,增强服务,简化开发) 减低程序之间的耦合 简化开发流程 通过切面编程以动态非侵入的方式增强服务 声明式事务的支持 方便测试 方便集成各种优秀的框

会写Bug的攻城狮 370

项目知识点-Spring-jdbc-过滤器登录-aop事务

简单的过滤器实现:判断用户是否登录,登录就放行。1.使用druid连接池。

dengfengling999的博客 688

Spring ioc 学习笔记

Spring是什么: Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。 提供了展现层 SpringMVC和持久层 Spring JDBCTemplate以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众...

MRchen009的博客 222

SPRING

spring是轻量级的开源的JavaEE框架,对对象打包,一般@bean适用类上,@Component , @Repository , @ Controller , @Service , @Configration)spring有两个核心部分:IOC(控制反转,把创建对象过程交给spring进行管理)和AOP(面向切面,不修改源代码进行功能增强)IOC工厂模式:在父类中提供一个创建对象的方法,允许子类决定实例对象的类型,创建对象的接口,让其子类决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。IO

CHIGGA666的博客 287

Spring框架-one(Spring框架介绍)

01-【熟悉】Spring框架介绍 1 Spring核心 1,AOP:面向切面编程。扩展功能而不修改源代码。 UserDaoImpl { void addUser(){ //得到sqlSessionFactory //得到sqlSession //开启事务 //调用mybatis的api做添加 //提交事务 //关闭sqlSession } ...

张子又 3377
上一篇: Mybatis环境搭建,CRUD,动态sql,缓存,延时加载
下一篇: (一)Redis介绍和Linux环境下安装
Java-fly
博客等级 码龄9年 13粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值