数据库访问#

注册数据源#

在Strato框架中,数据源通常由业务程序创建,并注册到com.strato.jdbc.datasource.v1_0_0.DataSourceFactory中。 我们建议每个部署单元都有一个bootstrap包,在其中定义一个BundleActivator,并初始化数据源、连接池等运行环境。例如:
//Bundle启动时初始化运行环境和相关资源
public class Activator implements BundleActivator{

	private TransactionInterceptor txInterceptor;

	@Override
	public void start(BundleContext bundleContext) throws Exception {
		{
			DruidDataSource datasource=new DruidDataSource();
			datasource.setUrl(GlobalEnvironment.getInstance().resolveString("${database.url}"));
			datasource.setUsername(GlobalEnvironment.getInstance().resolveString("${database.username}"));
			datasource.setPassword(GlobalEnvironment.getInstance().resolveString("${database.password}"));
			datasource.setMaxActive(GlobalEnvironment.getInstance().resolveInteger("${database.maxActive}"));
			datasource.setDefaultAutoCommit(false);
			datasource.setFilters("stat");
			setDataSourceProxyFilters(datasource);
			datasource.init();
			DataSourceFactory.getInstance().setDataSource(DataSourceFactory.COMMON_DATASOURCE, datasource);
		}
		

		this.txInterceptor=new TransactionInterceptor();
		DataSourceTransactionManager txManager=new DataSourceTransactionManager();
		txInterceptor.setTransactionManager(txManager);
		BundleUtil.exportServices(bundleContext, txInterceptor, null, null);
		BundleUtil.exportServices(bundleContext, txManager, null, null);
		
		FileServer.createServer("demoFileServer", GlobalEnvironment.getInstance().resolveString("${demo.fileserver.dir}"));
	}

	@Override
	public void stop(BundleContext context) throws Exception {
		DruidDataSource datasource = (DruidDataSource) DataSourceFactory.getInstance().getDataSource(DataSourceFactory.COMMON_DATASOURCE);
		datasource.close();
		DataSourceFactory.getInstance().removeDataSource(DataSourceFactory.COMMON_DATASOURCE);
	}

	private void setDataSourceProxyFilters(DruidDataSource datasource) {
		List<Filter> proxyFilters = new ArrayList<Filter>();
		StatFilter statFilter = new StatFilter();
		statFilter.setMergeSql(true);
		statFilter.setLogSlowSql(true);
		statFilter.setSlowSqlMillis(10000);
		
		proxyFilters.add(statFilter);
	
		Log4jFilter log4jFilter = new Log4jFilter();
		proxyFilters.add(log4jFilter);
		
		datasource.setProxyFilters(proxyFilters);
		
		//JdbcDataSourceStat
	}

}

上面的代码注册了一个名为“common”(COMMON_DATASOURCE)的数据源,并创建了事务拦截器,作为服务注入到OSGi容器中。

Mybatis集成#

Strato内置了对Mybatis的集成,开发者可以通过@MybatisMapper注解声明Mapper,并通过@MapperWired注解注入Mapper。 例如,Strato自带的LoginHistory默认实现,其中提供了Mapper:

@com.strato.orm.mybatis.v1_0_0.annotation.MybatisMapper
public interface LoginHistoryMapper {

    int countByExample(LoginHistoryExample example);


    int deleteByExample(LoginHistoryExample example);


    int deleteByPrimaryKey(String historyId);


    int insert(LoginHistory record);


    int insertSelective(LoginHistory record);
    
    ...
}
以上代码由Strato Mybatis UI自动生成,@com.strato.orm.mybatis.v1_0_0.annotation.MybatisMapper表明这是一个MybatisMapper,将被Strato扫描并注册。 一旦被成功注册,应用程序可用注解引入相应的Mapper,还是以LoginHistory为例:
@OsgiService(id="loginHistoryService")
public class LoginHistoryServiceImpl implements LoginHistoryService{
	
	@ConfigItem(name="strato.passport.datasource",comment="Passport的数据源名称",defaultValue=DataSourceFactory.COMMON_DATASOURCE)
	@MybatisWired(datasource="${strato.passport.datasource}")
	private LoginHistoryMapper loginHistoryMapper;

	@Override
	public int insert(LoginHistory history) {
		return loginHistoryMapper.insert(history);
	}
	
        ...
}

自动生成代码#

开发者可以通过MybatisUI工具自动从数据库反向生成Mapper XML、Java Model和Java Example代码。

@MybatisMapper#

MybatisMapper声明了一个Mapper定义,其注解定义如下:
package com.strato.orm.mybatis.v1_0_0.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MybatisMapper {

	String TYPE_CLASS="class";
	String TYPE_XML="xml";
	
	/**
	 * 若指定,扫描时则会从对应位置读取Mapper XML配置
	 * @return Location
	 */
	String value() default "";
	String type() default TYPE_XML;
}

@MybatisMapper支持xml和class两种模式,默认为xml(TYPE_XML)。 对于xml模式,value为对应的Mapper XML配置文件的类路径,value()==""时,默认取Class文件所在目录的上级目录下的同名.xml文件作为Mapper XML路径。 对于class模式,可以使用Mybatis自带的注解来描述Mapper接口,例如:
package com.strato.test.restful.impl.v1_0_0;

import org.apache.ibatis.annotations.Select;

import com.strato.orm.mybatis.v1_0_0.annotation.MybatisMapper;
import com.strato.test.restful.api.v1_0_0.User;

@MybatisMapper(type=MybatisMapper.TYPE_CLASS)
public interface TestMapper {

	@Select("select user_id userId,user_name name,gender,valid from t_user where user_id=${userId}")
	public User selectLoginUser(String userId);
}

@MybatisWired#

@MybatisWired定义了一个Mapper的引用,其注解定义如下:
package com.strato.orm.mybatis.v1_0_0.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.strato.jdbc.datasource.v1_0_0.DataSourceFactory;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MybatisWired {

	public static final String DEFAULT_DATASOURCE=DataSourceFactory.MERCHANT_DATASOURCE;
	
	public String datasource() default DEFAULT_DATASOURCE;
}

可以看到,@MybatisWired注入的Mapper是与数据源分离的,在运行期才动态获取数据源。开发者可以通过设置datasource属性,来指定该Mapper运行于哪个数据源之上。 其中,数据源来源于DataSourceFactory.getInstance().getDataSource(String datasourceName);

事务管理#

默认情况下,Mybatis将运行于一个REQUIRED属性的数据源事务管理器中(见本节的bootstrap Activator),Strato内置简单的数据源事务管理器,对拦截的所有调用,均提供成功后的commit操作和失败后的rollback操作。 尚不支持全局事务和分布式事务,对于一次性操作的多个数据源,会依次commit,但不保证数据的全局一致性。

事务环境默认提供REQUIRED的事务属性,在某些情况下,可能需要作事务的隔离,此时可以通过DataSourceTransactionManager API完成:

return DataSourceTransactionManager.requiresNew(new Execution<Boolean>() {
    @Override
    public Boolean execute() {
        //new transactional operation
    }
});

目前仅支持REQUIRES_NEW的API操作。

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-1) was last changed on 02-Jul-2017 17:44 by Jarez