Slick中无需db.run与for推导式读取自增ID,关联表插入失败求助
解决Scala中插入主表后关联表无数据写入的问题
我来帮你拆解代码里的问题,再给出能正常运行的修复方案:
核心问题分析
- 不可变集合的误用:你定义的
val transformedBookReaders = Seq[BookReaders]()是不可变的空序列,transformedBookReaders :+ ...只会返回一个新序列,不会修改原变量,导致action2始终对空序列执行插入操作。 - DBIO操作串联错误:
action1.andThen(action2)只是按顺序执行两个独立的数据库操作,action2完全拿不到action1生成的自增ID和转换后的关联数据,两者没有依赖关系。
修正后的代码
def savebook(book: Book, bookReaders: Seq[BookReaders]) = { // 串联插入主表和关联表的操作,放在同一个事务里 val transactionalAction = bookDAO.insertRow(book).flatMap { bookId => // 用刚拿到的自增ID转换生成关联表对象 val bookAssociations = bookReaders.map { bookReader => BookAssociation(None, bookId, bookReader.moduleId, bookReader.userId, bookReader.roleId) } // 执行关联表批量插入 bookAssocDao.insertRows(bookAssociations) } // 执行整个事务 db.run(transactionalAction.transactionally) }
关键改进说明
- 用flatMap串联依赖操作:
insertRow(book)返回的是DBIO[Long](假设自增ID为Long类型),通过flatMap可以在拿到bookId后直接生成并执行关联表的插入操作,让两个操作形成依赖关系,确保关联表能拿到正确的主表ID。 - 去掉无效的中间变量:直接在
flatMap内部生成关联表对象,避免了不可变集合赋值错误的问题。 - 事务包裹全流程:整个链式操作被
transactionally包裹,保证插入主表和关联表的操作要么全部成功,要么全部失败,维持数据一致性。
额外小提示
如果你的insertRows方法会返回受影响的行数,你也可以在flatMap末尾返回业务需要的结果(比如主表ID、关联表插入行数等),根据实际需求调整即可。
内容的提问来源于stack exchange,提问作者priyanka goel
相关产品推荐
相关产品推荐

