十、数据访问、JDBC事务
1、数据源的配置与构建(例:HikariCP DataSource)
HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池。
a.引入依赖
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
b.添加 HikariCP 数据源配置(具体参考:《数据源的配置与构建》)
solon.dataSources:
db_order!: #数据源命名,且加类型注册(即默认)
class: "com.zaxxer.hikari.HikariDataSource" #数据源类
jdbcUrl: "jdbc:mysql://localdb:3306/rock?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true"
driverClassName: "com.mysql.jdbc.Driver"
username: "demo"
password: "UL0hHlg0Ybq60xyb"
2、数据库操作框架集成
a.SqlUtils 集成
在 pom.xml 中引用 sqlutils 插件:
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-data-sqlutils</artifactId>
</dependency>
有了刚才的数据源配置后,直接就可以用了(不需要其它配置)。先以单数据源场景演示:
//使用示例
@Controller
public class DemoController{
@Inject
SqlUtils sqlUtils;
@Mapping("/user/")
public UserModel geUser(long puid){
return sqlUtils.sql("SELECT * FROM user WHERE puid=?", puid)
.queryRow()
.toBean(UserModel.class);
}
}
b.Mybatis集成
在 pom.xml 中引用 mybatis 适配插件
<dependency>
<groupId>org.noear</groupId>
<artifactId>mybatis-solon-plugin</artifactId>
</dependency>
使用 mybatis 时,还需要添加数据源相关的 mybatis mappers 及相关的属性配置
mybatis.db_order: #db_order 要与数据源的bean name 对上
typeAliases: #支持包名 或 类名(.class 结尾)
- "webapp.model"
mappers: #支持包名 或 类名(.class 结尾)或 xml(.xml结尾);配置的mappers 会 mapperScan并交由Ioc容器托管
- "webapp.dso.mapper.UserMapper.class"
现在可以开始用了
//使用示例
@Controller
public class DemoController{
//@Db 是 mybatis-solon-plugin 里的扩展注解,可注入 SqlSessionFactory,SqlSession,Mapper
//
@Db
UserMapper userDao; //UserMapper 已被 db_order 自动 mapperScan 并已托管,也可用 @Inject 注入
@Mapping("/user/")
public UserModel geUser(long puid){
return userDao.geUser(puid);
}
}
3、使用事务注解
Solon 中推荐使用 @Tran 注解来申明和管理事务。它适用于被动态代理的 Bean,如:@Controller、 @Remoting、@Component 注解的类;支持多数据源事务,使用方便。
a.SqlUtils的事务
//使用示例
@Controller
public class DemoController{
@Inject
SqlUtils sqlUtils;
@Tran
@Mapping("/user/add")
public Long addUser(UserModel user){
return sqlUtils.sql("INSERT INTO user(puid,user_name) VALUES(?,?)", user.getPuid(), user.getUserName())
.updateReturnKey();
}
}
b.Mybatis的事务
@Controller
public class DemoController{
@Db
UserMapper userDao; //UserMapper 已被 db_order mapperScan并已托管,也可用 @Inject 注入
@Tran
@Mapping("/user/add")
public Long addUser(UserModel user){
return userDao.addUser(user);
}
}
c.混合多框架、多数据源的事务(这个时候,我们需要Service层参演)
@Component
public class UserService{
@Inject("db_user") //数据源1
SqlUtils sqlUtils;
@Tran
public Long addUser(UserModel user){
return sqlUtils.sql("INSERT INTO user(puid,user_name) VALUES(?,?)", user.getPuid(), user.getUserName())
.updateReturnKey();
}
}
@Component
public class AccountService{
@Db("db_order") //数据库2
AccountMapper accountDao;
@Tran
public void addAccount(UserModel user){
accountDao.insert(user);
}
}
@Controller
public class DemoController{
@Inject
AccountService accountService;
@Inject
UserService userService;
@Tran
@Mapping("/user/add")
public Long geUser(UserModel user){
Long puid = userService.addUser(user); //会执行 db_user 事务
accountService.addAccount(user); //会执行 db_order 事务
return puid;
}
}