title: Service层事务
date: 2018-12-06 00:19:24
tags: 安卓开发
将dao层事务提升到service层
dao层就是数据库连接层,service层就是业务层,开发中我们通常将表映射成java对象形式,建立起dao层针对表的增删改查,但dao层的对象一般只针对一个表的操作,在实际开发中我们通常需要一次修改好几张表,比如在班级系统中,如果我删除某个班级,对应的应该删除班级对应的所有学生,可是夸表的操作就需要考虑到同步性,如果删除班级成功,删除学生失败,那么删除班级的操作应该也是撤销的,这需要回滚。
在网上很多教程中要不就是直接在dao层中添加事务,不然就是使用spring框架自动开启事务。可是安卓中没有spring框架,只好手动实现一个了。
首先考虑到事务是在service层实现的,所以我们的数据库对象应当控制在service层中。为了避免不断创建新的数据库对象,我们使用ThreadLocal类给每一个线程储存一个数据库对象,这样可以有效避免资源浪费,也不会造成如单例模式的数据库连接单一而排队产生的等待。
实现思路
创建一个TransactionManager类统一管理事务的开启和关闭,提供回调接口,在service层中创建数据库对象并存入ThreadLocal中,在dao层中从线程中获取数据库对象,这样就可以保证我们在统一线程中获取到的数据库对象是一样的。
class TransactionManager(private val context: Context) {
private val TAG = TransactionManager::class.java.name
public fun doTransaction(doTransactionListener: DoTransactionListener ){
doAsync {
// 创建数据库对象
val db = MyDatabaseOpenHelper.writeDb(context)
db.beginTransaction()
// 开启事务
try {
// 数据库操作
doTransactionListener.run()
// 设置事务成功
db.setTransactionSuccessful()
uiThread {
// 成功回调
doTransactionListener.success()
}
}catch (e: SQLException){
e.printStackTrace()
uiThread {
// 失败回调
doTransactionListener.error(e)
}
}finally {
// 提交事务
db.endTransaction()
db.close()
}
}
}
interface DoTransactionListener{
/**
* 数据库操作
*/
fun run()
/**
* 失败回调
*/
fun error(e: SQLException)
/**
* 成功回调
*/
fun success()
}
}
class MyDatabaseOpenHelper(context: Context) : SQLiteOpenHelper(context, DB_NAME,null,1) {
val TAG = "MyDatabaseOpenHelper"
companion object {
// 写 数据库 线程对象
private val wtol = ThreadLocal<SQLiteDatabase>()
// 读 数据库 线程对象
private val rtol = ThreadLocal<SQLiteDatabase>()
fun writeDb(context: Context): SQLiteDatabase {
var db = wtol.get()
Log.v("DBDB"," 获取数据库对象")
if(db == null) {
db = MyDatabaseOpenHelper(context).writableDatabase
wtol.set(db)
Log.v("DBDB"," 创建数据库写对象")
}
return db
}
fun readDb(context: Context): SQLiteDatabase {
var db = rtol.get()
if(db == null) {
db = MyDatabaseOpenHelper(context).readableDatabase
rtol.set(db)
}
return db
}
}
}
/**
* dao层
*/
class ClassesDaoImpl(private val context: Context) : IClassesDao {
/**
* 插入
* @param obj 班级对象
* @return
*/
override fun insert(obj: Classes): Long {
val writeDatabase = MyDatabaseOpenHelper.writeDb(context)
val cv = ContentValues()
cv.put("class_id", obj.classId)
cv.put("class_name", obj.className)
cv.put("info", obj.info)
cv.put("institute", obj.institute)
cv.put("speciality", obj.speciality)
cv.put("create_time", obj.createTime)
return writeDatabase.insert(CLASSES_TABLE, null, cv)
}
}
/**
* service层
*/
class ClassesServiceImpl(private val context: Context) : IClassesService {
private val classesDao: IClassesDao = ClassesDaoImpl(context)
override fun saveClasses(className: String, info: String, institute: String, speciality: String): Classes? {
val classes = Classes()
classes.classId = generateRefID()
classes.className = className
classes.info = info
classes.institute = institute
classes.speciality = speciality
classes.createTime = getNow()
val re = classesDao.insert(classes)
return if (re > 0) {
classes
} else null
}
}
代码中使用
TransactionManager(this).doTransaction(object : TransactionManager.DoTransactionListener{
/**
* 数据库操作
*/
override fun run() {
classesService.deleteClassesByClassId(item.classId)
}
/**
* 失败回调
*/
override fun error(e: android.database.SQLException) {
toast("删除失败")
}
/**
* 成功回调
*/
override fun success() {
toast("删除成功")
}
})
参考文章:https://blog.youkuaiyun.com/qyy_123456_qyy/article/details/82353257
https://blog.youkuaiyun.com/qq_36115651/article/details/79871813