2023新版Spring6全新讲解-核心内容之事务管理

Spring核心之事务

在这里插入图片描述

一、JdbcTemplate

  JdbcTemplate是Spring框架对JDBC操作进行的封装,可以简化方便对数据库的操作。

1.数据库表结构

准备一张普通的表

CREATE TABLE `t_student` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(32) DEFAULT NULL,`age` int DEFAULT NULL,`sex` varchar(3) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB

2.创建项目

  创建一个普通的maven项目。添加相关的依赖

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.0.2</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.19</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.12</version></dependency><!--log4j2的依赖--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.19.0</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j2-impl</artifactId><version>2.19.0</version></dependency><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.2</version><scope>provided</scope></dependency></dependencies>

添加db.properties属性文件。定义数据库的连接信息

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
jdbc.user=root
jdbc.password=123456

然后完成spring的配置文件的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 引入第三方的属性文件 --><context:property-placeholder location="classpath:db.properties"/><!-- 开启扫描 --><context:component-scan base-package="com.boge"/><!-- 配置下数据库的连接 --><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="url" value="${jdbc.url}"/><property name="driver" value="${jdbc.driver}" /><property name="username" value="${jdbc.user}" /><property name="password" value="${jdbc.password}" /></bean><!-- 我们需要注入JdbcTemplate对象 --><bean class="org.springframework.jdbc.core.JdbcTemplate"><!-- 关联数据源 --><property name="dataSource" ref="dataSource"/></bean></beans>

创建Student的实体对象

@Data
public class Student {private Integer id;private String name;private Integer age;private String sex;
}

然后我们就可以做数据库的相关操作了

3.数据库的操作

  我们需要创建Dao接口并定义相关的方法。

public interface IStudentDao {public List<Student> list();public int save(Student student);public int update(Student student);public int deleteById(Integer id);
}

然后创建接口的对应的实现

package com.boge.dao.impl;import com.boge.dao.IStudentDao;
import com.boge.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;@Repository
public class StudentDaoImpl implements IStudentDao {@Autowiredprivate JdbcTemplate jdbcTemplate;/* @Overridepublic List<Student> list() {String sql = "select * from t_student";return jdbcTemplate.query(sql,new BeanPropertyRowMapper<Student>(Student.class));}*/@Overridepublic List<Student> list() {String sql = "select * from t_student";return jdbcTemplate.query(sql, new RowMapper<Student>() {@Overridepublic Student mapRow(ResultSet rs, int rowNum) throws SQLException {Student stu = new Student();stu.setId(rs.getInt("id"));stu.setName(rs.getString("name"));stu.setAge(rs.getInt("age"));stu.setSex(rs.getString("sex"));return stu;}});}@Overridepublic int save(Student student) {String sql = "insert into t_student(name,age,sex)values(?,?,?)";int count = jdbcTemplate.update(sql, student.getName(), student.getAge(), student.getSex());return count;}@Overridepublic int update(Student student) {String sql = "update t_student set name=? ,age = ? ,sex=? where id=?";int count = jdbcTemplate.update(sql,student.getName(),student.getAge(),student.getSex(),student.getId());return count;}@Overridepublic int deleteById(Integer id) {String sql = "delete from t_student where id = ?";return jdbcTemplate.update(sql,id);}
}

然后我们就可以单元测试了

package com.boge.test;import com.boge.dao.IStudentDao;
import com.boge.entity.Student;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.event.TransactionalEventListener;import java.util.List;public class JdbcTemplateTest {@Testpublic void testQuery(){ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");IStudentDao bean = ac.getBean(IStudentDao.class);List<Student> list = bean.list();for (Student student : list) {System.out.println(student);}}@Testpublic void testSave(){ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");IStudentDao bean = ac.getBean(IStudentDao.class);Student student = new Student();student.setName("boge");student.setAge(18);student.setSex("男");System.out.println(bean.save(student));}@Testpublic void testUpdate(){ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");IStudentDao bean = ac.getBean(IStudentDao.class);Student student = new Student();student.setId(1);student.setName("boge66");student.setAge(22);student.setSex("男");System.out.println(bean.update(student));}@Testpublic void testDelete(){ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");IStudentDao bean = ac.getBean(IStudentDao.class);System.out.println(bean.deleteById(1));}
}

二、事务处理

1.相关概念介绍

1.1 什么是事务

  数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

image.png

1.2 事务的特性

A:原子性(Atomicity)

  一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

C:一致性(Consistency)

事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。

如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。

如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。

I:隔离性(Isolation)

  指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。

D:持久性(Durability)

  指的是只要事务成功结束,它对数据库所做的更新就必须保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

2.编程式事务

事务功能的相关操作全部通过自己编写代码来实现:

Connection conn = ...;try {// 开启事务:关闭事务的自动提交conn.setAutoCommit(false);// 核心操作// 提交事务conn.commit();}catch(Exception e){// 回滚事务conn.rollBack();}finally{// 释放数据库连接conn.close();}

编程式的实现方式存在缺陷:

  1. 细节没有被屏蔽:具体操作过程中,所有细节都需要程序员自己来完成,比较繁琐。
  2. 代码复用性不高:如果没有有效抽取出来,每次实现功能都需要自己编写代码,代码就没有得到复用。

3.声明式事务

  既然事务控制的代码有规律可循,代码的结构基本是确定的,所以框架就可以将固定模式的代码抽取出来,进行相关的封装。

封装起来后,我们只需要在配置文件中进行简单的配置即可完成操作。

  • 好处1:提高开发效率
  • 好处2:消除了冗余的代码
  • 好处3:框架会综合考虑相关领域中在实际开发环境下有可能遇到的各种问题,进行了健壮性、性能等各个方面的优化

所以,我们可以总结下面两个概念:

  • 编程式:自己写代码实现功能
  • 声明式:通过配置让框架实现功能

4.基于注解的声明式事务

4.1 案例准备

创建相关的表结构

CREATE TABLE `t_user` (`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',`username` varchar(32) DEFAULT NULL COMMENT '账号',`balance` int unsigned DEFAULT NULL COMMENT '余额',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ;CREATE TABLE `t_goods` (`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(32) DEFAULT NULL COMMENT '商品名称',`price` int DEFAULT NULL COMMENT '商品价格',`stock` int unsigned DEFAULT NULL COMMENT '商品库存',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 

创建Dao相关的代码

public interface GoodsDao {// 查询商品的价格Integer queryPriceById(Integer goodsId);// 更新商品的库存void updateGoodsStock(Integer goodsId);// 更新用户的余额void updateUserBalance(Integer userId,Integer price);
}
@Repository
public class GoodsDaoImpl implements GoodsDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic Integer queryPriceById(Integer goodsId) {String sql = "select price from t_goods where id = ?";return jdbcTemplate.queryForObject(sql,Integer.class,goodsId);}@Overridepublic void updateGoodsStock(Integer goodsId) {String sql = "update t_goods set stock = stock - 1 where id = ?";jdbcTemplate.update(sql,goodsId);}@Overridepublic void updateUserBalance(Integer userId, Integer price) {String sql = "update t_user set balance = balance - ? where id = ?";jdbcTemplate.update(sql,price,userId);}
}

然后就是创建对应的Service

public interface GoodsService {void buyGoods(Integer userId,Integer goodsId);
}
@Service
public class GoodsServiceImpl implements GoodsService {@Autowiredprivate GoodsDao dao;@Overridepublic void buyGoods(Integer userId, Integer goodsId) {// 1.查询商品的价格Integer price = dao.queryPriceById(goodsId);// 2.更新库存数量dao.updateGoodsStock(goodsId);// 3.更新用户的余额dao.updateUserBalance(userId,price);}
}

然后就是对应的Controller

@Controller
public class GoodsController {@Autowiredprivate GoodsService service;public void buyGoods(){service.buyGoods(1,1);}
}

然后我们可以做无事务的案例测试:

在数据库中我们简单的准备两条数据

image.png

image.png

然后测试

    @Testpublic void testQuery(){ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");GoodsController bean = ac.getBean(GoodsController.class);bean.buyGoods();}

执行上面的代码。控制台报错:

image.png

原因是:购买的商品的价格是80,用户的余额是50、那么扣减80后。用户的余额为-30。但是我们设置的balance的字段是无符号的int类型。是不能存储负数的。所以报错。

image.png

也就是上面的多个操作。前面的成功了。后面的失败了。那么就出现了数据的安全问题。

4.2 事务的处理

  上面的业务逻辑我们需要通过事务管理。先通过注解的方式来实现。我们需要在配置文件中添加tx标签

image.png

然后添加事务管理器和放开注解

image.png

然后通过@Transactionl注解来开启事务:

  • 可以写在类的头部:对类中的所有的方法生效
  • 也可以写在方法头部:对方法生效

4.3 事务隔离级别

  数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。

隔离级别一共有四种:

  • 读未提交:READ UNCOMMITTED
    允许Transaction01读取Transaction02未提交的修改。
  • 读已提交:READ COMMITTED、
    要求Transaction01只能读取Transaction02已提交的修改。
  • 可重复读:REPEATABLE READ
    确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。
  • 串行化:SERIALIZABLE
    确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。

各个隔离级别解决并发问题的能力见下表:

隔离级别脏读不可重复读幻读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

各种数据库产品对事务隔离级别的支持程度:

隔离级别OracleMySQL
READ UNCOMMITTED×
READ COMMITTED√(默认)
REPEATABLE READ×√(默认)
SERIALIZABLE

使用方式

@Transactional(isolation = Isolation.DEFAULT)//使用数据库默认的隔离级别
@Transactional(isolation = Isolation.READ_UNCOMMITTED)//读未提交
@Transactional(isolation = Isolation.READ_COMMITTED)//读已提交
@Transactional(isolation = Isolation.REPEATABLE_READ)//可重复读
@Transactional(isolation = Isolation.SERIALIZABLE)//串行化

4.4 事务的传播属性

什么是事务的传播行为?

image.png

image.png

在service类中有a()方法和b()方法,a()方法上有事务,b()方法上也有事务,当a()方法执行过程中调用了b()方法,事务是如何传递的?合并到一个事务里?还是开启一个新的事务?这就是事务传播行为。

一共有七种传播行为:

  • REQUIRED:支持当前事务,如果不存在就新建一个(默认)【没有就新建,有就加入】
  • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行【有就加入,没有就不管了】
  • MANDATORY:必须运行在一个事务中,如果当前没有事务正在发生,将抛出一个异常【有就加入,没有就抛异常】
  • REQUIRES_NEW:开启一个新的事务,如果一个事务已经存在,则将这个存在的事务挂起【不管有没有,直接开启一个新事务,开启的新事务和之前的事务不存在嵌套关系,之前事务被挂起】
  • NOT_SUPPORTED:以非事务方式运行,如果有事务存在,挂起当前事务【不支持事务,存在就挂起】
  • NEVER:以非事务方式运行,如果有事务存在,抛出异常【不支持事务,存在就抛异常】
  • NESTED:如果当前正有一个事务在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于外层事务进行提交或回滚。如果外层事务不存在,行为就像REQUIRED一样。【有事务的话,就在这个事务里再嵌套一个完全独立的事务,嵌套的事务可以独立的提交和回滚。没有事务就和REQUIRED一样。】

image.png

image.png

4.5 配置类的方式

  现在使用配置文件的方式已经非常少了。我们基本都是通过配置类的方式来使用的。所以我们还是需要掌握下在全配置类的方式下的事务使用。

定义对应的配置类。然后在配置类中注入 DataSource、JdbcTemplate和事务管理器对象

package com.boge.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;/*** 这就是我们自定义的Java配置类*/
@Configuration
@ComponentScan(basePackages = {"com.boge"}) // 指定扫描路径
// 开启事务注解
@EnableTransactionManagement
public class SpringConfig {@Beanpublic DataSource getDataSource(){DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&useSSL=false&serverTimezone=UTC");dataSource.setUsername("root");dataSource.setPassword("123456");return dataSource;}@Bean(name = "jdbcTemplate")public JdbcTemplate getJdbcTemplate(DataSource dataSource){JdbcTemplate template = new JdbcTemplate();// 关联对应的数据源template.setDataSource(dataSource);return template;}@Beanpublic DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();// 关联数据源dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}}

然后就是测试案例代码

 @Testpublic void testTx(){ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);GoodsController bean = ac.getBean(GoodsController.class);bean.buyGoods();}

5.基于XML的声明式事务

  虽然说现在很少通过XML的方式来使用事务了。但是作为程序员我们还是需要了解这部分的内容。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 引入第三方的属性文件 --><context:property-placeholder location="db.properties"/><!-- 开启扫描 --><context:component-scan base-package="com.boge"/><!-- 配置下数据库的连接 --><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.user}" /><property name="password" value="${jdbc.password}" /></bean><!-- 我们需要注入JdbcTemplate对象 --><bean class="org.springframework.jdbc.core.JdbcTemplate"><!-- 关联数据源 --><property name="dataSource" ref="dataSource"/></bean><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"><!-- 关联对应的数据源 --><property name="dataSource" ref="dataSource"/></bean><!--tx:advice:事务通知--><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!--tx:method:配置具体的事务方法--><tx:method name="buyGoods" read-only="false"/><tx:method name="get*" read-only="true"/><tx:method name="query*" read-only="true"/><tx:method name="find*" read-only="true" /><!-- 添加 修改 删除 --><tx:method name="save*" read-only="false" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/><tx:method name="update*" read-only="false" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/><tx:method name="delete*" read-only="false" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/><tx:method name="remove*" read-only="false" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/></tx:attributes></tx:advice><aop:config><aop:advisor advice-ref="txAdvice" pointcut="execution(* com.boge.service.impl.*.*(..))"/></aop:config></beans>

然后是测试代码

    @Testpublic void testTx2(){ApplicationContext ac = new ClassPathXmlApplicationContext("spring-xml.xml");GoodsController bean = ac.getBean(GoodsController.class);bean.buyGoods();}

当然在这块我们需要添加 AspjectJ的依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.2</version></dependency>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/351280.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

树和子树的定义

在数据结构中存在一种叫“树”的结构。 树的定义&#xff1a; 树&#xff08;tree&#xff09;是由n&#xff08;n>0)个节点&#xff08;或元素&#xff09;组成的有限集合&#xff08;记为T&#xff09;。 如果n0&#xff0c;它是一棵空树&#xff0c;这是树的特征。如果…

“树的子结构”

描述 输入两棵二叉树A&#xff0c;B&#xff0c;判断B是不是A的子结构。&#xff08;我们约定空树不是任意一个树的子结构&#xff09; 假如给定A为{8,8,7,9,2,#,#,#,#,4,7}&#xff0c;B为{8,9,2}&#xff0c;2个树的结构如下&#xff0c;可以看出B是A的子结构 数据范围: 0…

华为OD机试题【导师请吃火锅】【2023 B卷 100分】

文章目录 &#x1f3af; 前言&#x1f3af; 题目描述&#x1f3af; 解题思路&#x1f4d9; Python实现代码&#x1f4d7; Java实现代码&#x1f4d8; C语言实现&#xff1a; &#x1f3af; 前言 &#x1f3c6; 《华为机试真题》专栏含2023年牛客网面经、华为面经试题、华为OD机…

树的结构-树的各种定义及性质

树&#xff1a; n个结点组成的有限集合。 &#xff08;1&#xff09;有且仅有一个特定的称为根的结点。 &#xff08;2&#xff09;当n>1时&#xff0c;其余结点可分为m个互不相交的有限集合&#xff0c;其中每个集合本身又是一棵树&#xff0c;称为根节点的子树。 注意&…

VTK-vtkInformation

前言&#xff1a;本博文主要介绍vtk中的接口vtkInformation的应用&#xff0c;以及vtkInformation的衍生用法&#xff0c;希望对各位小伙伴有所帮助&#xff0c;谢谢&#xff01; 目录 vtkInformation介绍 描述&#xff1a; Information中接受的类型&#xff1a; 方法 vtk…

半导体(TSS)放电管的两大选购注意事项及选型小策略

固体放电管&#xff0c;是以半导体工艺制作而成的&#xff0c;因此我们也称为半导体&#xff08;TSS&#xff09;放电管&#xff0c;它常在电路中并联使用&#xff0c;具备伏安特性。 TSS放电管在电路中类似开关&#xff0c;在正常工作时不动作&#xff0c;但一般被保护电路受到…

PRE、RC、beta、RTM 含义扫盲

alpha版:内部测试版。α是希腊字母的第一个,表示最早的版本,一般用户不要下载这个版本,这个版本一般是作为技术预览的,很可能包含很多BUG,功能也不全,主要是给开发人员和测试人员测试和找BUG用的。——————————————————————————————————…

直播预告|RTM 助力信令与消息全球实时互通

RTM 是实时消息&#xff08;Real-time Messaging&#xff09;的简称。在实时互动场景中&#xff0c;用户通常有两种互动方式&#xff1a;一种是通过音视频进行互动&#xff0c;比如语音连麦、视频连麦等&#xff1b;另一种是通过非音视频的方式进行互动&#xff0c;比如文字聊天…

数据库sql server 2008 r2 RTM版本升级到sql server 2012 r2

(数据库sql server 2008 r2 RTM版本升级到2012) 1.先介绍sql 2008数据库的几个版本 10.00.1600其实就是SQL 2008 10.50.1600其实就是SQL 2008 R2 10.50.2500其实就是SQL 2008 R2 SP1 10.50.4000其实就是SQL Server 2008 R2 SP2 SQL Server 版本号汇总 那么sql server 2008后…

IBM LSF学习(是什么)

碎碎念&#xff1a;这里主要介绍&#xff0c;LSF是什么&#xff0c;本人秉承的写作原则或者技术学习原则&#xff0c;“是什么”&#xff0c;“为什么”&#xff0c;“怎么用”。 这里借鉴了这几篇文章并进行自我理解&#xff1a; https://blog.csdn.net/qq_43653083/article/d…

微软服务器操作系统指什么意思,现代服务器操作系统:你绝对想不到是什么!...

大家好&#xff0c;小编又和大家见面了。上一篇文章&#xff0c;我们了解了Windows Server 2008&#xff0c;今天&#xff0c;我们讲一讲Windows Server 2012。 Windows Server 2012(开发代号&#xff1a;Windows Server 8)是微软的一个服务器系统。这是Windows 8的服务器版本&…

直播选择 RTC 还是 RTMP?

RTC 实时直播 RTC&#xff08;Real Time Communication&#xff09;实时音视频通信&#xff0c;它最大的特点就是低延时和无卡顿。从功能流程上说&#xff0c;它包含了采集、编码、前后处理、传输、解码、缓冲、渲染等诸多环节&#xff0c;每一个细分环节&#xff0c;还有更细…

灰度测试是什么意思

本文章&#xff0c;百度论坛知乎等处查询&#xff0c;了解灰度测试&#xff0c;方便学习。本文章只限学习。文章可能内容多&#xff0c;我进行了网上查询终结&#xff0c;还需细看整理&#xff0c;如有重复内容请见谅&#xff0c;我也正在了解&#xff0c;方便手机携带查看。 …

MySQL安装流程 及 8.0与5.7区别

一、MySQL版本介绍 1、MySQL 8.0 窗口函数&#xff1a;MySQL 8.0版本支持窗口函数&#xff0c;这是数据分析工作中非常常用的一类函数。窗口函数可以让用户在单个查询中跨多个行检索数据&#xff0c;并在查询结果中对数据执行计算。隐藏索引&#xff1a;在MySQL 8.0版本中&am…

探究Cache缓存功能---【pytest】

前言 pytest运行完用例之后会生成一个 .pytest_cache的缓存文件夹&#xff0c;用于记录用例的ids和上一次失败的用例。 1、跑自动化时经常会出现这样一个情况&#xff0c;一轮自动化跑完后零星出现了几个失败测试用例&#xff0c;无法断定失败的原因&#xff0c;所以可能需要重…

浏览器插件检测淘宝订单是否淘客下单

1、插件安装 。 2、获取接口秘钥 &#xff0c;获取之后请将接口秘钥填写到本插件中。 3、登录淘宝/天猫已卖出报表列表&#xff0c;点击【检测淘客】按钮&#xff0c;等待返回检测结果&#xff1b;

帝国CMS淘宝客插件,帝国自动调用淘宝客插件链接自动转换

插件功能 可以根据根据设置的字段自动调用淘宝客商品数量&#xff0c;适用于各种资讯和导购站 具体看演示地址&#xff0c;可根据自己的样式来调用数据

淘宝客接入PHP(一)

1、文件位置 extend/tbk文件里面 2、引入tbk的sdk Loader::import(TopSdk, EXTEND_PATH."/tbk/taobaoke");3、修改autoload文件 直接运行报一下错误&#xff0c;是因为这个类给了namespace的原因。 两种解决方案&#xff0c;1、删除namespace 2、修改为spl_autoloa…

淘宝开放平台Api的小试牛刀(获取淘宝客推广商品信息)

最近在学习淘宝开放平台&#xff0c;属于初学小菜鸟&#xff0c;有一点点小成就给大家分享一下。 要做这个东西&#xff0c;第一步你必须注册为淘宝开发方平台的开发人员。地址&#xff1a;http://open.taobao.com/index.htm 点击加入开放平台&#xff0c; 配图&#xff1a;…