天天看点

aka-dbutils与Spring集成

aka-dbutils与Spring集成

aka-dbutils可以很好的与Spring继承,如果与Spring继承,则aka-dbutils里自带的Tomcat JDBC连接池将不会被使用,而是转而使用Spring容器配置管理的连接池DataSource。你可以通过aka-dbutils-spring模块和Spring集成。

Spring集成

与spring集成首先必须引入maven依赖如下:

<dependency>
   <artifactId>aka-dbutils-spring</artifactId>
   <groupId>com.github.ulwx</groupId>
   <version>1.0.3.1</version>
</dependency>

           

下面以一个完整的例子(aka-dbutils-spring-test)来介绍如何与Spring集成。

例子工程(aka-dbutils-spring-test)的maven配置如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <artifactId>aka-dbutils-spring-test</artifactId>
   <groupId>com.github.ulwx</groupId>
   <version>1.0.3.1</version>
   <parent>
      <groupId>com.github.ulwx</groupId>
      <artifactId>aka-dbutils-parent</artifactId>
      <version>1.0.3.1</version>
      <relativePath>../aka-dbutils-parent/pom.xml</relativePath>
   </parent>
   <properties>
      <spring.version>5.3.1</spring.version>
   </properties>
   <dependencies>
      <dependency>
         <artifactId>aka-dbutils-spring</artifactId>
         <groupId>com.github.ulwx</groupId>
          <!-- 由于在 aka-dbutils-parent里的<dependencyManagement>元素下指定了aka-dbutils-spring的版本号,
	         所以aka-dbutils-spring在没有指定版本号的情况下,使用的是<dependencyManagement>其中指定的版本号
          -->
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>${spring.version}</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-aspects</artifactId>
         <version>${spring.version}</version>
      </dependency>
      <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-dbcp2</artifactId>
         <version>2.8.0</version>
      </dependency>
      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>8.0.23</version>
      </dependency>
   </dependencies>
</project>
           

例子工程目录如下:

aka-dbutils与Spring集成

下面为MyConfiguration配置类,用于声明数据源及事务相关的配置。

package com.github.ulwx.aka.dbutils.database.spring.test;
......
@EnableTransactionManagement(proxyTargetClass = true)
@EnableAspectJAutoProxy(exposeProxy = true)   //暴露代理对象,这样可以通过 AopContext.currentProxy()获取代理对象
@Configuration
@ComponentScan
public class MyConfiguration {

    @Bean(destroyMethod = "close")
    public BasicDataSource dataSource() {       
        BasicDataSource dataSource = new BasicDataSource();  //使用的是commons-dbcp2数据源
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?x=1&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false");
        dataSource.setUsername("root");
        dataSource.setPassword("abcd");
        dataSource.setMaxWaitMillis(10000);
        dataSource.setInitialSize(1);
        dataSource.setMaxTotal(10);
        dataSource.setMinEvictableIdleTimeMillis(6000);
        return dataSource;

    }
    @Bean  //定义事务管理器,Bean名称为transactionManager,这样业务方法上的@Transactional的注解就不必指定transactionManager属性
    public DataSourceTransactionManager transactionManager() {    
        DataSourceTransactionManager dt = new DataSourceTransactionManager();
        dt.setDataSource(dataSource()); //④
        return dt;
    }
    @Bean   //定义MDataBaseFactory类型工厂Bean用于在DataBaseTemplate Bean里获取MDataBase实例
    public MDataBaseFactory mDataBaseFactory() {
        MDataBaseFactory mDataBaseFactory = 
                 new MDataBaseFactory(dataSource()); //③ 一定要和上面④处使用同一个数据源,不然不会应用上事务
        mDataBaseFactory.setTableColumRule(DbConst.TableNameRules.underline_to_camel);  //①
        mDataBaseFactory.setTableNameRule(DbConst.TableColumRules.underline_to_camel);  //②
        return mDataBaseFactory;

    }
    @Bean  //定义MDataBaseTemplate类型Bean,此Bean会被注入到业务实体(Service或Dao)中,从而可以进行数据库操作
    public MDataBaseTemplate mDataBaseTemplate() {
        return new MDataBaseTemplate(mDataBaseFactory());
    }

}


           

上面的MyConfiguration配置类里,可以看到必须要定义MDataBaseFactory类型的Bean,在Bean里可以配置表名和表列到Java类和属性名称的转换规则,同时需要传入一个数据源,表明在此数据源上进行操作。还必须定义一个MDataBaseTemplate类型的Bean,通过这个Bean注入到你的业务实体从而进行数据库操作。需要注意的是③处对MDataBaseFactory构造函数传入的数据源一定和DataSourceTransactionManager里传入的数据源一致,这样才能应用到Spring的事务机制。

Address类

package com.github.ulwx.aka.dbutils.database.spring.test;
import com.github.ulwx.aka.dbutils.tool.support.ObjectUtils;
import com.github.ulwx.aka.dbutils.database.MdbOptions;
public class Address extends MdbOptions implements java.io.Serializable {

	private String name;/*;len:20*/
	private Integer addressId;/*;len:10*/
	private Long custormerId;/*;len:19*/
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return name;
	}
	public void setAddressId(Integer addressId){
		this.addressId = addressId;
	}
	public Integer getAddressId(){
		return addressId;
	}
	public void setCustormerId(Long custormerId){
		this.custormerId = custormerId;
	}
	public Long getCustormerId(){
		return custormerId;
	}
	public String toString(){
		return  ObjectUtils.toString(this);
	}
	private static final long serialVersionUID =556120941L;

}
           

AddressDao类

package com.github.ulwx.aka.dbutils.database.spring.test;
......
@Component
public class AddressDao {
    private MDataBaseTemplate mDataBaseTemplate; //通过构造方法被注入,后面可以 通过MDataBaseTemplate对象操作数据库
    public AddressDao(MDataBaseTemplate mDataBaseTemplate){
        this.mDataBaseTemplate=mDataBaseTemplate;
    }
    public List<Address> getListMd(){
        Map<String, Object> mp=new HashMap<>();
        List<Address> list=mDataBaseTemplate.queryList(Address.class,
                MD.md(),mp);
        return list;
    }
    @Transactional(propagation = Propagation.NESTED)
    public void updateMd(){
        Map<String, Object> mp=new HashMap<>();
        mDataBaseTemplate.update(MD.md(),mp);
    }
}
///AddressDao.md
getListMd
===
select * from address

updateMd
===
UPDATE
`address`
SET
`name` = '111111'
WHERE  `address_id` = 1

           

MyService类

package com.github.ulwx.aka.dbutils.database.spring.test;
......
@Service
public class MyService {
    private AddressDao addressDao;
    public MyService(AddressDao addressDao) {
        this.addressDao = addressDao;
    }
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateMdb(){
        List<Address> list2= addressDao.getListMd();
        //声明了Propagation.NESTED事务
        addressDao.updateMd();
       //MyService方法的内部调用会使用被调用方法上声明的事务失效,所以需要用下面方式调用
        ((MyService) AopContext.currentProxy()).updateMdbOther();
        //MyService方法的内部调用会使用被调用方法上声明的事务失效,下面的内部调用还是在updateMdb()方法的事务里。
        //updateMdbOther();

    }
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void updateMdbOther(){
        System.out.println("call updateMdbOther");
    }
}
           

ApplicationTest类

package com.github.ulwx.aka.dbutils.database.spring.test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class ApplicationTest {
    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext ctx =
                new AnnotationConfigApplicationContext(MyConfiguration.class);
        MyService myService=(MyService)ctx.getBean("myService");
        myService.updateMdb();

    }
}

           

至此与Spring集成的例子介绍完毕,读者可以发现与MyBatis有很多相似之处。

关于本节的例子你可以到https://github.com/ulwx/aka-dbutils-spring-test下载。