Spring4笔记9--Spring的事务管理(AOP应用的例子)
Spring的事务管理:
事务原本是数据库中的概念,在 Dao 层。但一般情况下,需要将事务提升到业务层,即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。
在 Spring 中通常可以通过以下三种方式来实现对事务的管理:
(1)使用 Spring 的事务代理工厂管理事务
(2)使用 Spring 的事务注解管理事务
(3)使用 AspectJ 的 AOP 配置管理事务
Spring事务管理API:
Spring 的事务管理,主要用到两个事务相关的接口。
(1)事务管理器接口
事务管理器是 PlatformTransactionManager 接口对象。其主要用于完成事务的提交、回滚,及获取事务的状态信息。查看 SpringAPI 帮助文档:Spring 框架解压目录下的docs/javadoc-api/index.html。
Modifier and Type | Method and Description |
---|---|
void |
commit(TransactionStatus status)
Commit the given transaction, with regard to its status.
|
TransactionStatus |
getTransaction(TransactionDefinition definition)
Return a currently active transaction or create a new one, according to the specified propagation behavior.
|
void |
rollback(TransactionStatus status)
Perform a rollback of the given transaction.
|
A、常用的两个实现类
PlatformTransactionManager 接口有两个常用的实现类:
DataSourceTransactionManager:使用 JDBC 或 iBatis 进行持久化数据时使用。
HibernateTransactionManager:使用 Hibernate 进行持久化数据时使用。
B、Spring 的回滚方式
Spring 事务的默认回滚方式是:发生运行时异常时回滚,发生受查异常时提交。不过,对于受查异常,程序员也可以手工设置其回滚方式。
(2)事务定义接口:
事务定义接口 TransactionDefinition 中定义了事务描述相关的三类常量:事务隔离级别、事务传播行为、事务默认超时时限,及对它们的操作。
A、定义了五个事务隔离级别常量:
这些常量均是以 ISOLATION_开头。即形如 ISOLATION_XXX。
DEFAULT:采用DB默认的事务隔离级别。MySql的默认为REPEATABLE_READ; Oracle默认为 READ_COMMITTED。
READ_UNCOMMITTED:读未提交。未解决任何并发问题。
READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。
REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读
SERIALIZABLE:串行化。不存在并发问题。
B、定义了七个事务传播行为常量
所谓事务传播行为是指,处于不同事务中的方法在相互调用时,执行期间事务的维护情况。如,A 事务中的方法 doSome()调用 B 事务中的方法 doOther(),在调用执行期间事务的维护情况,就称为事务传播行为。事务传播行为是加在方法上的。
事务传播行为常量都是以 PROPAGATION_ 开头,形如 PROPAGATION_XXX。
REQUIRED:指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务。这种传播行为是最常见的选择,也是Spring 默认的事务传播行为。
如该传播行为加在 doOther()方法上。若 doSome()方法在执行时就是在事务内的,则 doOther()方法的执行也加入到该事务内执行。若 doSome()方法没有在事务内执行,则 doOther()方法会创建一个事务,并在其中执行。
SUPPORTS:指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。
MANDATORY:指定的方法必须在当前事务内执行,若当前没有事务,则直接抛出异常。
REQUIRES_NEW:总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。
NOT_SUPPORTED:指定的方法不能在事务环境中执行,若当前存在事务,就将当前事务挂起。
NEVER:指定的方法不能在事务环境下执行,若当前存在事务,就直接抛出异常。
NESTED:指定的方法必须在事务内执行。若当前存在事务,则在嵌套事务内执行;若当前没有事务,则创建一个新事务。
C、定义了默认事务超时时限
常量 TIMEOUT_DEFAULT 定义了事务底层默认的超时时限,及不支持事务超时时限设置的 none 值。
注意,事务的超时时限起作用的条件比较多,且超时的时间计算点较复杂。所以,该值一般就使用默认值即可。
Spring事务代码详解:
要求:实现模拟购买股票。存在两个实体:银行账户 Account 与股票账户 Stock。当要购买股票时,需要从 Account 中扣除相应金额的存款,然后在 Stock 中增加相应的股票数量。而在这个过程中,可能会抛出一个用户自定义的异常。异常的抛出,将会使两个操作回滚。
Step1:创建数据库表 account、stock
Step2:创建实体类 Account 与 Stock (略)
Step3:定义 Dao 接口 IAccountDao 与 IStockDao
package com.tongji.dao; public interface IAccountDao { void insertAccount(String aname, double money); void updateAccount(String aname, double money, boolean isBuy); }
package com.tongji.dao; public interface IStockDao { void insertStock(String sname, int amount); void updateStock(String sname, int amount, boolean isBuy); }
Step4:定义 Dao 实现类 AccountDaoImpl 与 StockDaoImpl
package com.tongji.dao; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao { @Override
public void insertAccount(String aname, double money) {
String sql = "insert into account(aname, balance) values(?,?)";
this.getJdbcTemplate().update(sql, aname, money);
} @Override
public void updateAccount(String aname, double money, boolean isBuy) {
String sql = "update account set balance=balance+? where aname=?";
if (isBuy) {
sql = "update account set balance=balance-? where aname=?";
}
this.getJdbcTemplate().update(sql, money, aname); } }
package com.tongji.dao; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class StockDaoImpl extends JdbcDaoSupport implements IStockDao { @Override
public void insertStock(String sname, int amount) {
String sql = "insert into stock(sname, count) values (?,?)";
this.getJdbcTemplate().update(sql , sname, amount);
} @Override
public void updateStock(String sname, int amount, boolean isBuy) {
//isBuy为true,则表示购买股票,此时应增加股票账户中的股票数量
String sql = "update stock set count=count-? where sname=?";
if (isBuy) {
sql = "update stock set count=count+? where sname=?";
}
this.getJdbcTemplate().update(sql, amount, sname);
} }
Step5:定义异常类 StockException
package com.tongji.beans; public class StockException extends Exception {
private static final long serialVersionUID = 5377570098437361228L; public StockException() {
super();
} public StockException(String message) {
super(message);
} }
Step6:定义 Service 接口 IStockProcessService
package com.tongji.service; public interface IStockProcessService {
void openAccount(String aname, double money);
void openStock(String sname, int amount);
void buyStock(String aname, double money, String sname, int amount);
}
Step7:定义 service 的实现类 StockProcessServiceImpl
package com.tongji.service; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.tongji.beans.StockException;
import com.tongji.dao.IAccountDao;
import com.tongji.dao.IStockDao; public class StockProcessServiceImpl implements IStockProcessService{
private IAccountDao accountDao;
private IStockDao stockDao; public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
} public void setStockDao(IStockDao stockDao) {
this.stockDao = stockDao;
} @Override
public void openAccount(String aname, double money) {
accountDao.insertAccount(aname, money);
} @Override
public void openStock(String sname, int amount) {
stockDao.insertStock(sname, amount);
} @Override
public void buyStock(String aname, double money, String sname, int amount) throws StockException {
boolean isBuy = true;
accountDao.updateAccount(aname, money, isBuy);
//故意抛出异常
if (true) {
throw new StockException("购买股票异常");
}
stockDao.updateStock(sname, amount, isBuy);
} }
Step8:定义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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 注册数据源:C3P0数据源 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册Dao -->
<bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean>
</beans>
Step9:测试类
package com.tongji.test; import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.tongji.service.IStockProcessService; public class MyTest { private IStockProcessService service; @Before
public void before() {
//创建容器
@SuppressWarnings("resource")
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
service = (IStockProcessService) ac.getBean("stockService");
} @Test
public void testOpen() {
service.openAccount("张三", 10000);
service.openStock("华为", 5);
} @Test
public void testBuyStock() {
service.buyStock("张三", 2000, "华为", 5);
} }
此配置文件没有采用事务管理,所以购买股票的时候,出现了数据库中账户金额减少了,但是股票数目没有增加的不一致情况。
使用 Spring 的事务代理工厂管理事务:
该方式是,需要为目标类,即 Service 的实现类创建事务代理。事务代理使用的类是TransactionProxyFactoryBean,该类需要初始化如下一些属性:
(1)transactionManager:事务管理器
(2)target:目标对象,即 Service 实现类对象
(3)transactionAttributes:事务属性设置
对于 XML 配置代理方式实现事务管理时,受查异常的回滚方式,程序员可以通过以下方式进行设置:通过“-异常”方式,可使发生指定的异常时事务回滚;通过“+异常”方式,可使发生指定的异常时事务提交。
修改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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 注册数据源:C3P0数据源 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册Dao -->
<bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean> <!-- 事务 -->
<!-- 注册事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 生成事务代理 -->
<bean id="stockServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="myTxManager"/>
<property name="target" ref="stockService"/>
<property name="transactionAttributes">
<props>
<prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
<prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-StockException</prop>
</props>
</property>
</bean>
</beans>
由于本项目使用的是 JDBC 进行持久化,所以使用 DataSourceTransactionManager 类作为事务管理器。
修改测试类:
public void before() {
//创建容器
@SuppressWarnings("resource")
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
service = (IStockProcessService) ac.getBean("stockServiceProxy");
}
使用 Spring 的事务注解管理事务:
通过@Transactional 注解方式,也可将事务织入到相应方法中。而使用注解方式,只需在配置文件中加入一个 tx 标签,以告诉 spring 使用注解来完成事务的织入。该标签只需指定一个属性,事务管理器。
修改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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 注册数据源:C3P0数据源 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册Dao -->
<bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean> <!-- 事务 -->
<!-- 注册事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 开启注解驱动 -->
<tx:annotation-driven transaction-manager="myTxManager"/>
</beans>
修改 service 的实现类 StockProcessServiceImpl:
package com.tongji.service; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.tongji.beans.StockException;
import com.tongji.dao.IAccountDao;
import com.tongji.dao.IStockDao; public class StockProcessServiceImpl implements IStockProcessService{
private IAccountDao accountDao;
private IStockDao stockDao; public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
} public void setStockDao(IStockDao stockDao) {
this.stockDao = stockDao;
} @Override
@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED)
public void openAccount(String aname, double money) {
accountDao.insertAccount(aname, money);
} @Override
@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED)
public void openStock(String sname, int amount) {
stockDao.insertStock(sname, amount);
} @Override
@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED, rollbackFor=StockException.class)
public void buyStock(String aname, double money, String sname, int amount) throws StockException {
boolean isBuy = true;
accountDao.updateAccount(aname, money, isBuy);
if (true) {
throw new StockException("购买股票异常");
}
stockDao.updateStock(sname, amount, isBuy);
} }
@Transactional 的所有可选属性如下所示:
propagation:用于设置事务传播属性。该属性类型为 Propagation 枚举,默认值为Propagation.REQUIRED。
isolation:用于设置事务的隔离级别。该属性类型为 Isolation 枚举,默认值为Isolation.DEFAULT。
readOnly:用于设置该方法对数据库的操作是否是只读的。该属性为 boolean,默认值为 false。
timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为 int,默认值为-1,即没有时限。
rollbackFor:指定需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
rollbackForClassName:指定需要回滚的异常类类名。类型为 String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
noRollbackFor:指定不需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
noRollbackForClassName:指定不需要回滚的异常类类名。类型为 String[],默认值为空数组。当然,若只有一个异常类时,可以不使用数组。
需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非public 方法,如果加上了注解@Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该方法中。因为 Spring 会忽略掉所有非 public 方法上的@Transaction 注解。
若@Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。
使用 AspectJ 的 AOP 配置管理事务(重点):
使用 XML 配置事务代理的方式的不足是,每个目标类都需要配置事务代理。当目标类较多,配置文件会变得非常臃肿。使用 XML 配置顾问方式可以自动为每个符合切入点表达式的类生成事务代理。
修改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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 注册数据源:C3P0数据源 -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean> <!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/> <!-- 注册Dao -->
<bean id="accountDao" class="com.tongji.dao.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.tongji.dao.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.tongji.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean> <!-- 事务 -->
<!-- 注册事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册事务通知 -->
<tx:advice id="txAdvice" transaction-manager="myTxManager">
<tx:attributes>
<!-- 指定在连接点方法上应用的事务属性 -->
<tx:method name="open*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="StockException"/>
</tx:attributes>
</tx:advice> <!-- AOP配置 -->
<aop:config>
<!-- 指定切入点 -->
<aop:pointcut expression="execution(* *..service.*.*(..))" id="stockPointCut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="stockPointCut"/>
</aop:config>
</beans>
总结:Spring 的事务管理,是 AOP 的应用,将事务作为切面织入到了 Service 层的业务方法中。
Spring4笔记9--Spring的事务管理(AOP应用的例子)的更多相关文章
- Spring初学之spring的事务管理注解
spring的事务管理,本文的例子是:比如你需要网购一本书,卖书的那一方有库存量以及书的价格,你有账户余额.回想我们在编程中要实现买书这样的功能,由于你的账户表和书的库存量表肯定不是同一张数据库表,所 ...
- Spring学习笔记五:Spring进行事务管理
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776256.html 事务管理主要负责对持久化方法进行统一的提交或回滚,Spring进行事务管理即我们无需在 ...
- Spring事务管理—aop:pointcut expression 常见切入点表达式及事务说明
Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明 例: <aop:config> <aop:pointcut expression= ...
- 二十 Spring的事务管理及其API&事务的传播行为,编程式&声明式(xml式&注解式,底层AOP),转账案例
Spring提供两种事务方式:编程式和声明式(重点) 前者需要手写代码,后者通过配置实现. 事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACI ...
- Hibernate与Spring的事务管理
什么是事务 这个问题比较大,按照我的理解就是,一个事务内的n个操作,要么全部完成,一旦有一个操作有问题,那么所有的操作都全部回滚. Jdbc的事务 首先,大家已经知道了,事务说白了就是一个词----统 ...
- Spring的事务管理
事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...
- Spring应用——事务管理
事务基础:请参看:http://www.cnblogs.com/solverpeng/p/5720306.html 一.Spring 事务管理 1.前提:事务管理器 在使用 Spring 声明式事务管 ...
- spring,mybatis事务管理配置与@Transactional注解使用[转]
spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关 ...
- Spring高级事务管理难点剖析
1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没 ...
- CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)
JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...
随机推荐
- delphi手动创建dataset并插入值
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, Syste ...
- Angular中ui-select的使用
Angular中ui-select的使用 最近工作一直很忙,没有时间整理知识,前几天项目中需要用到angular-ui-select,实现下拉框快速过滤效果,今天有时间研究了一下,终于搞明白了. 一. ...
- 每日一问(如何在List中加入、设置、获取和删除其中的元素?)
作为集合接口的一部分,对List接口所做的操作,最常见的就是增删查改了.这里总结下JAVA 中List接口及实现该接口的类实现这些操作的方法. 一.增加新的元素的方法 在Collection接口中定义 ...
- 【BZOJ4991】我也不知道题目名字是什么(线段树)
[BZOJ4991]我也不知道题目名字是什么(线段树) 题面 BZOJ 题解 对于线段树维护的区间维护以下东西: 区间左(右)端开始(结束)的最长(短)子串的长度 左端右端的值,以及当前区间内的答案 ...
- Palindrome Number - LeetCode
目录 题目链接 注意点 解法 小结 题目链接 Palindrome Number - LeetCode 注意点 负数肯定是要return false的 数字的位数要分奇数和偶数两种情况 解法 解法一: ...
- mybatis.5.动态SQL
1.动态SQL,解决关联sql字符串的问题,mybatis的动态sql基于OGNL表达式 if语句,在DeptMapper.xml增加如下语句; <select id="selectB ...
- laravel 实用扩展包
1.beyondcode / laravel-self-diagnosis 环境检测.检测 php 版本.扩展 是否正常,数据库连接是否正常等 2.nunomaduro/larastan larave ...
- mac 必备工具
iTerm 可以在一个窗口中垂直.水平分割窗口,而不用切换来切换去 一些基本功能如下: 1.分窗口操作:shift+command+d(横向)command+d(竖向) 2.查找和粘贴:command ...
- Eureka的原理
http://blog.csdn.net/awschina/article/details/17639191 关于AWS的区域和可用区概念解释: Eureka的原理:Region与Zone. 因为在编 ...
- 读Bayes' Theorem
Bayes' Theorem定理的原理说明,三个简单的例子来说明用法及一些练习. Bayes' Theorem就是概率问题,论文相对比较好理解,也不必做什么笔记.