Java Persistence with MyBatis 3(中国版) 第五章 与Spring集成
MyBatis-Spring它是MyBatis子模块框。它用来提供流行的依赖注入框架Spring无缝集成。
Spring框架是一个基于依赖注入(Dependency Injection)和面向切面编程(Aspect Oriented Programming,AOP)的Java框架,鼓舞使用基于POJO的编程模型。
另外,Spring提供了声明式和编程式的事务管理能力。能够非常大程度上简化应用程序的数据訪问层(data access layer)的实现。在本章中,我们将看到在基于Spring的应用程序中使用MyBatis而且使用Spring的基于注解的事务管理机制。
本章将包括下面话题:
- 在Spring应用程序中配置MyBatis
安装
配置MyBatis Beans
- 使用SqlSession
- 使用映射器
- 使用Spring进行事务管理
5.1 在Spring应用程序中配置MyBatis
本节将讨论怎样在基于Spring的应用程序中安装和配置MyBatis。
5.1.1 安装
假设你正在使用Maven构建工具,你能够配置MyBatis的spring依赖例如以下:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.1.3.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.1.3.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>假设你没有使用Maven。你能够从http://code.google.com/p/mybatis/上下载mybatis-spring-1.2.0-boundle.zip。将其加入,将mybatis-1.2.0.jar包加入到classpath中。
你能够从http://www.springsource.org/download/community/上下载Spring框架包spring-framework-3.1.3.RELEASE.zip。将其内全部jar包加入到classpath中。
假设你仅仅使用MyBatis而没有使用Spring,在每个方法中,我们须要手动创建SqlSessionFactory对象,并且从SqlSessionFactory对象中创建SqlSession。并且我们还要负责提交或者回滚事务、关闭SqlSession对象。
通过使用MyBatis-Spring模块,我们能够在Spring的应用上下文ApplicationContext中配置MyBatis Beans,Spring会负责实例化SqlSessionFactory对象以及创建SqlSession对象,并将其注入到DAO或者Service类中。而且,你能够使用Spring的基于注解的事务管理功能,不用自己在数据訪问层中书写事务处理代码了。
5.1.2 配置MyBatis Beans
为了让Spring来实例化MyBatis组件如SqlSessionFactory、SqlSession、以及映射器Mapper对象。我们须要在Spring的bean配置文件里配置它们,如果在applicationContext.xml中。配配置例如以下:
<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource. DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/elearning" />
<property name="username" value="root" />
<property name="password" value="admin" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliases" value="com.mybatis3.domain.Student, com.mybatis3.domain.Tutor" />
<property name="typeAliasesPackage" value="com.mybatis3.domain" />
<property name="typeHandlers" value="com.mybatis3.typehandlers.PhoneTypeHandler" />
<property name="typeHandlersPackage" value="com.mybatis3.typehandlers" />
<property name="mapperLocations" value="classpath*:com/mybatis3/**/*.xml" />
<property name="configLocation" value="WEB-INF/mybatisconfig.xml" />
</bean>
</beans>使用上述的bean定义,Spring会使用例如以下配置属性创建一个SqlSessionFactory对象:
- ž dataSource:它引用了dataSource bean
- ž typeAliases:它指定了一系列的全然限定名的类名列表,用逗号隔开。这些别名将通过默认的别名规则创建(将首字母小写的非无全然限定类名作为别名)。
- ž typeAliasesPackage:它指定了一系列包名列表,用逗号隔开,包内含有须要创建别名的JavaBeans。
- ž typeHandlers:它指定了一系列的类型处理器类的全然限定名的类名列表,用逗号隔开。
- ž typeHandlersPackage: 它指定了一系列包名列表。用逗号隔开。包内含有须要被注冊的类型处理器类。
- ž mapperLocations:它指定了SQL映射器Mapper XML配置文件的位置
- configLocation:它指定了MyBatisSqlSessionFactory配置文件所在的位置。
5.2 使用SqlSession
一旦SqlSessionFactory bean被配置,我们须要配置SqlSessionTemplate bean。SqlSessionTemplatebean 是一个线程安全的Spring bean,我们能够从中获取到线程安全的SqlSession对象。
因为SqlSessionTemplate提供线程安全的SqlSession对象,你能够在多个Spring bean实体对象中共享SqlSessionTemplate对象。从概念上看,SqlSessionTemplate和Spring的DAO模块中的JdbcTemplate很相似。
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>如今我肯能够将SqlSessionbean实体对象注射到随意的Springbean实体中,然后使用SqlSession对象调用SQL映射语句。
public class StudentDaoImpl implements StudentDao
{
private SqlSession sqlSession;
public void setSqlSession(SqlSession session)
{
this.sqlSession = session;
}
public void createStudent(Student student)
{
StudentMapper mapper =
this.sqlSession.getMapper(StudentMapper.class);
mapper.insertStudent(student);
}
}假设你正在使用基于XML来配置Spring beans,你能够将SqlSessionbean实体对象注射到StudenDaoImpl bean 实体对象中。例如以下:
<bean id="studentDao" class="com.mybatis3.dao.StudentDaoImpl">
<property name="sqlSession" ref="sqlSession" />
</bean>假设你使用基于注解的方式配置Spring beans。你例如以下将SqlSession bean实体对象注入到StudentDaoImplbean实体对象中:
@Repository
public class StudentDaoImpl implements StudentDao
{
private SqlSession sqlSession;
@Autowired
public void setSqlSession(SqlSession session)
{
this.sqlSession = session;
}
public void createStudent(Student student)
{
StudentMapper mapper =
this.sqlSession.getMapper(StudentMapper.class);
mapper.insertStudent(student);
}
}还有第二种注入Sqlsession对象的方法,即。通过拓展继承SqlSessionDaoSupport。这样的方式让我们能够在运行映射语句时,增加不论什么自己定义的逻辑。
public class StudentMapperImpl extends SqlSessionDaoSupport implements
StudentMapper
{
public void createStudent(Student student)
{
StudentMapper mapper =
getSqlSession().getMapper(StudentMapper.class);
mapper.insertAddress(student.getAddress());
//Custom logic
mapper.insertStudent(student);
}
}<bean id="studentMapper" class="com.mybatis3.dao.StudentMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>在以上的这些方式中。我们注入了SqlSession对象,获取Mapper实例,然后运行映射语句。
这里Spring会为我们提供一个线程安全的SqlSession对象,以及当方法结束后关闭SqlSession对象。
然而。MyBatis-Spring模块提供了更好的方式,我们能够不通过SqlSession获取映射器Mapper,直接注射Sql映射器Mapper bean。我们下节将讨论它。
5.3 使用映射器
我们能够使用MapperFactoryBean将映射器Mapper接口配置成Spring bean实体。
例如以下所看到的:
public interface StudentMapper
{
@Select("select stud_id as studId, name, email, phone from
students where stud_id=#{id}")
Student findStudentById(Integer id);
}<bean id="studentMapper" class="org.mybatis.spring.mapper. MapperFactoryBean">
<property name="mapperInterface" value="com.mybatis3.mappers. StudentMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>如今StudentMapper bean实体对象能够被注入到随意的Spring bean实体对象中,并调用映射语句方法,例如以下所看到的:
public class StudentService
{
private StudentMapper studentMapper;
public void setStudentMapper (StudentMapperstudentMapper)
{
this. studentMapper = studentMapper;
}
public void createStudent(Student student)
{
this.studentMapper.insertStudent(student);
}
}<bean id="studentService" class="com.mybatis3.services. StudentService">
<property name="studentMapper" ref="studentMapper" />
</bean>分别配置每个映射器Mapper接口是一个很单调的过程。
我们能够使用MapperScannerConfigurer来扫描包(package)中的映射器Mapper接口。并自己主动地注冊。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mybatis3.mappers" />
</bean>假设映射器Mapper接口在不同的包(package)中,你能够为basePackage属性指定一个以逗号分隔的包名列表。
MyBatis-Spring-1.2.0介绍了两种新的扫描映射器Mapper接口的方法:
- l 使用<mybatis:scan/>元素
- l 使用@MapperScan注解(需Spring3.1+版本号)
5.3.1 <mybatis:scan />
<mybatis:scan>元素将在特定的以逗号分隔的包名列表中搜索映射器Mapper接口。使用这个新的MyBatis-Spring名空间你须要加入下面的schema声明:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://mybatis.org/schema/mybatis-spring
http://mybatis.org/schema/mybatis-spring.xsd">
<mybatis:scan base-package="com.mybatis3.mappers" />
</beans><mybatis:scan>元素提供了下列的属性来自己定义扫描过程:
- annotation: 扫描器将注冊全部的在base-package包内而且匹配指定注解的映射器Mapper接口。
- factory-ref:当Spring上下文中有多个SqlSessionFactory实例时。须要指定某一特定的SqlSessionFactory来创建映射器Mapper接口。
正常情况下,仅仅有应用程序中有一个以上的数据源才会使用。
- ž marker-interface: 扫描器将注冊在base-package包中的而且继承了特定的接口类的映射器Mapper接口
- ž template-ref: 当Spring上下文中有多个SqlSessionTemplate实例时。须要指定某一特定的SqlSessionTemplate来创建映射器Mapper接口。正常情况下,仅仅有应用程序中有一个以上的数据源才会使用。
- name-generator:BeannameGenerator类的全然限定类名,用来命名检測到的组件。
5.3.2 MapperScan
Spring 框架3.x+版本号支持使用@Configuration和@Bean 注解来提供基于Java 的配置。假设你倾向于使用基于Java的配置,你能够使用@MapperScan注解来扫描映射器Mapper接口。@MapperScan和<mybatis:scan/>工作方式同样,而且也提供了相应的自己定义选项。
@Configuration
@MapperScan("com.mybatis3.mappers")
public class AppConfig
{
@Bean
public DataSource dataSource()
{
return new PooledDataSource("com.mysql.jdbc.Driver",
"jdbc:mysql://localhost:3306/elearning", "root", "admin");
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception
{
SqlSessionFactoryBeansessionFactory = new
SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
return sessionFactory.getObject();
}
}@MapperScan注解有下面属性供自己定义扫描过程使用:
ž annotationClass: 扫描器将注冊全部的在base-package包内而且匹配指定注解的映射器Mapper接口。
ž markerInterface: 扫描器将注冊在base-package包中的而且继承了特定的接口类的映射器Mapper接口
ž sqlSessionFactoryRef:当Spring 上下文中有一个以上的SqlSesssionFactory时,用来指定特定SqlSessionFactory
ž sqlSessionTemplateRef: 当Spring 上下文中有一个以上的sqlSessionTemplate时,用来指定特定sqlSessionTemplate
ž nameGenerator:BeanNameGenerator类用来命名在Spring容器内检測到的组件。
ž basePackageClasses:basePackages()的类型安全的替代品。包内的每个类都会被扫描。
ž basePackages:扫描器扫描的基包,扫描器会扫描内部的Mapper接口。注意包内的至少有一个方法声明的才会被注冊。详细类将会被忽略。
5.4 使用Spring进行事务管理
仅仅使用MyBatis。你须要写事务控制相关代码,如提交或者回退数据库操作。
public Student createStudent(Student student)
{
SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().
openSession();
try
{
StudentMapper mapper =
sqlSession.getMapper(StudentMapper.class);
mapper.insertAddress(student.getAddress());
mapper.insertStudent(student);
sqlSession.commit();
return student;
}
catch (Exception e)
{
sqlSession.rollback();
throw new RuntimeException(e);
}
finally
{
sqlSession.close();
}
}我们能够使用Spring的基于注解的事务处理机制来避免书写上述的每一个方法中控制事务的冗余代码。
为了能使用Spring的事务管理功能,我们须要在Spring应用上下文中配置TransactionManagerbean实体对象:
<bean id="transactionManager"
class="org.springframework.jdbc. datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>事务管理器引用的dataSource和SqlSessionFactory bean使用的dataSource同样。
在Spring中使用基于注解的事务管理特性,例如以下:
<tx:annotation-driven transaction-manager="transactionManager"/>如今你能够在Spring service bean上使用@Transactional注解。表示在此service中的每个方法都应该在一个事务中执行。假设方法成功执行完成,Spring会提交操作。假设有执行期异常发生,则会执行回滚操作。另外,Spring会将MyBatis 的异常转换成合适的DataAccessExceptions,这样会为特定错误上提供额外的信息。
@Service
@Transactional
public class StudentService
{
@Autowired
private StudentMapper studentMapper;
public Student createStudent(Student student)
{
studentMapper.insertAddress(student.getAddress());
if(student.getName().equalsIgnoreCase(""))
{
throw new RuntimeException("Student name should not be
empty.");
}
studentMapper.insertStudent(student);
return student;
}
}以下是一个Spring的applicationContext.xml完毕配置:
<beans>
<context:annotation-config />
<context:component-scan base-package="com.mybatis3" />
<context:property-placeholder location="classpath:application.properties" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mybatis3.mappers" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliases"
value="com.mybatis3.domain.Student,com.mybatis3.domain.Tutor" />
<property name="typeAliasesPackage" value="com.mybatis3.domain" />
<property name="typeHandlers" value="com.mybatis3.typehandlers.PhoneTypeHandler" />
<property name="typeHandlersPackage" value="com.mybatis3.typehandlers" />
<property name="mapperLocations" value="classpath*:com/mybatis3/**/*.xml" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
</beans>如今让我们写一个独立的測试client来測试StudentService,例如以下:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml"
)
public class StudentServiceTest
{
@Autowired
private StudentService studentService;
@Test
public void testCreateStudent()
{
Address address = new Address(0, "Quaker Ridge
Rd.", "Bethel", "Brooklyn", "06801", "USA");
Student stud = new Student();
long ts = System.currentTimeMillis();
stud.setName("stud_" + ts);
stud.setEmail("stud_" + ts + "@gmail.com");
stud.setAddress(address);
Student student = studentService.createStudent(stud);
assertNotNull(student);
assertEquals("stud_" + ts, student.getName());
assertEquals("stud_" + ts + "@gmail.com", student.getEmail());
System.err.println("CreatedStudent: " + student);
}
@Test(expected = DataAccessException.class)
public void testCreateStudentForException()
{
Address address = new Address(0, "Quaker Ridge
Rd.", "Bethel", "Brooklyn", "06801", "USA");
Student stud = new Student();
long ts = System.currentTimeMillis();
stud.setName("Timothy");
stud.setEmail("stud_" + ts + "@gmail.com");
stud.setAddress(address);
studentService.createStudent(stud);
fail("You should not reach here");
}
}这里在testCreateStudent()方法中,我们为Address和Student赋上了合适的数据,所以Address和Student会被分别插入到表ADDRESSES和STUDENTS中。在testCreateStudentForException()方法我们设置了名字为Timothy,该名称在数据库中已经存在了,所以当你尝试将此student记录插入到数据库中。MySQL会抛出一个UNIQUE
KEY 冲突的异常。Spring会将此异常转换成DataAccessException异常。而且将插入ADDRESSES表中的数据回滚(rollback)掉。
5.5 总结
在本章中我们学习了如何将MyBatis与Spring框架集成。我们还学习了如何安装Spring类库而且在Spring 的应用上下文ApplicationContext上注冊MyBatis bean实体对象。
我们还看到如何配置和注入SqlSession和Mapper bean实体对象以及调用映射语句。我们还学习了利用Spring基于注解的事务处理机制来使用MyBatis。
你已经读完本书,祝贺你!
如今,你应该知道如何高效地使用MyBatis与数据库工作。你学会了如何发挥你的Java和SQL技巧的优势使MyBatis更富有成效。
你知道了如何以更清晰的方式使用MyBatis写出数据持久化代码,不用管被MyBatis框架处理的全部底层细节。
另外,你学会了如何在最流行的依赖注入框架-Spring中使用MyBatis。
MyBatis框架很易于使用,但它提供了强大的特性。因此它对于基于Java的项目而言。是一个很好的数据库持久化解决方式。
MyBatis也提供了一些工具如MyBatis Generator(http://www.mybatis.org/generator/),能够被用来从已经存在的数据库schema中,产生持久化代码如数据库实体(databaseentities),映射器Mapper 接口,MapperXML配置文件,使MyBatis入门很方便。另外,MyBatis还有它的姊妹项目如MyBatis.NET和MyBatis-Scala,分别为.NET
和Scala编程语言提供了一样强大的特性。MyBatis随着每个版本号的公布。添加了一些特性。正变得越来越好。想了解很多其它的新特性,你能够訪问MyBatis官方站点https://code.google.com/p/mybatis/.订阅MyBatis 的使用者邮件列表是一个不错的想法。我们祝你一切顺利,编码快乐!(We
wish you all the best, and happy coding!)
《Java Persistence with MyBatis 3(中文版)》导航:
Java Persistence with MyBatis 3(中文版)
Java Persistence with MyBatis 3(中文版) 前言
Java Persistence with MyBatis 3(中文版) 第一章 MyBatis入门
Java Persistence with MyBatis 3(中文版) 第二章 引导MyBatis
Java Persistence with MyBatis 3(中文版) 第三章 使用XML配置SQL映射器
Java Persistence with MyBatis 3(中文版) 第四章 使用注解配置SQL映射器
Java Persistence with MyBatis 3(中文版) 第五章 与Spring集成
-----------------------------------------------------------------------------------------------------------------------
作者声明:这篇文章是源http://blog.csdn.net/luanlouis,如需转载。转载请注明出处。
Java Persistence with MyBatis 3(中国版) 第五章 与Spring集成的更多相关文章
- Java Persistence with MyBatis 3(中国版)
译者的话 前段时间因为工作和学习的须要,我打算深入研究MyBatis框架.于是在网上查找关于MyBatis的教程,发现国内网上关于MyBatis的教程资料少得可怜:除了MyBatis官网上的用户使用手 ...
- Java Persistence with MyBatis 3(中文版) 第五章 与Spring集成
MyBatis-Spring是MyBatis框架的子模块,用来提供与当前流行的依赖注入框架Spring的无缝集成. Spring框架是一个基于依赖注入(Dependency Injection)和面向 ...
- Java Persistence with MyBatis 3(中文版) 第二章 引导MyBatis
MyBatis最关键的组成部分是SqlSessionFactory,我们可以从中获取SqlSession,并执行映射的SQL语句.SqlSessionFactory对象可以通过基于XML的配置信息或者 ...
- Java Persistence with MyBatis 3(中文版) 第三章 使用XML配置SQL映射器
关系型数据库和SQL是经受时间考验和验证的数据存储机制.和其他的ORM 框架如Hibernate不同,MyBatis鼓励开发者可以直接使用数据库,而不是将其对开发者隐藏,因为这样可以充分发挥数据库服务 ...
- Java Persistence with MyBatis 3(中文版) 第一章 MyBatis入门
本章将涵盖以下话题: ž MyBatis是什么? ž 为什么选择MyBatis? ž MyBatis安装配置 ž 域模型样例 1.1 MyBatis是什么 MyBatis是一个简化和实现了Ja ...
- Java Persistence with MyBatis 3(中文版) 前言
对很多软件系统而言,保存数据到数据库和从数据库中检索数据是其工作流程中至关重要的一部分.在 Java 领域,有很多的实现了数据持久化层的工具和框架,它们每一个都有自己不同的实现方法.而 MyBatis ...
- Java Persistence with MyBatis 3(中文版)
译者的话 前段时间由于工作和学习的需要,我打算深入研究MyBatis框架.于是在网上查找关于MyBatis的教程,发现国内网上关于MyBatis的教程资料少得可怜:除了MyBatis官网上的用户使用手 ...
- MyBatis从入门到精通(第9章):Spring集成MyBatis(下)
MyBatis从入门到精通(第9章):Spring集成MyBatis(下) springmvc执行流程原理 mybatis-spring 可以帮助我们将MyBatis代码无缝整合到Spring中.使 ...
- MyBatis从入门到精通(第9章):Spring集成MyBatis(中)
MyBatis从入门到精通(第9章):Spring集成MyBatis(中) 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法.应该将应用自身的设计和具体 ...
随机推荐
- 【转】Robot Framework 快速入门
目录 介绍 概述 安装 运行demo 介绍样例应用程序 测试用例 第一个测试用例 高级别测试用例 数据驱动测试用例 关键词keywords 内置关键词 库关键词 用户定义关键词 变量 定义变量 使用变 ...
- 第七章——DMVs和DMFs(4)——用DMV和DMF监控磁盘IO
原文:第七章--DMVs和DMFs(4)--用DMV和DMF监控磁盘IO 前言: 本文为本系列最后一篇,作为DBA,你必须经常关注磁盘的I/O问题,一旦出现问题,要尽快分析出是什么问题.SQLServ ...
- 性能优化——统计信息——SQLServer自动更新和自动创建统计信息选项
原文:性能优化--统计信息--SQLServer自动更新和自动创建统计信息选项 原文译自:http://www.mssqltips.com/sqlservertip/2766/sql-server-a ...
- 二元最近的共同祖先问题(O(n) time 而且,只有一次遍历,O(1) Space (它不考虑函数调用栈空间))
问题: 找到两个节点的二叉树的最近的共同祖先. 首先可以参考这个博客http://blog.csdn.net/cxllyg/article/details/7635992 ,写的比較具体,包含了节点包 ...
- Sonar——代码质量管理平台
Sonar——代码质量管理平台 一.基本认识 Sonar (SonarQube)是一个开源平台,用于管理源代码的质量. Sonar 不只是一个质量数据报告工具,更是代码质量管理平台.通过插件机制,So ...
- 对LevelDB的“升级版”存储引擎RocksDB的调研成果
Google的leveldb是个非常优秀的存储引擎.但还是有一些不尽人意的地方,比方leveldb不支持多线程合并.对key范围查找的支持还非常easy,未做优化措施,等等.而Facebook的Roc ...
- Nginx+Php-fpm+MySQL+Redis源码编译安装指南
说明:本教程由三部分组成如下: 1. 源码编译安装Nginx 2. 源码编译安装php以及mysql.redis扩展模块 3. 配置虚拟主机 文中所涉及安装包程序均提供下 ...
- CSDN博客导出工具 Mac By Swift
写这篇文章的主要目的是了解Swift语言本身,如何以及Objc和第三方交互框架 必须先用CSDN帐户登录.您可以导出所有的博客文章,加入YAML当首标信息,包括对应标签和分类在头制品信息,和底座式(原 ...
- NSIS:静默释放文件并运行 制作绿色单文件软件
原文 NSIS:静默释放文件并运行 制作绿色单文件软件 现在所谓的绿色单文件软件,大多与以下代码原理相似:把软件运行需要的文件封装为一个EXE文件,双击时释放到某个目录(大多是TEMP)并运行主程序文 ...
- 使用PF_PACKET和SOCK_RAW发送自己定义type以太网数据包
本文介绍使用PF_PACKET和SOCK_RAW发送自己定义type以太网数据包,使用wireshare抓包能够获取到数据包,为Linux内核添加网络协议做铺垫. 先上码: #include < ...