Scala Doobie 没有将值插入数据库

Scala Doobie not inserting values into database

我插入值的代码是:

def insert(link: entity.Link) : IO[Int] = {
    logger.info("Inserting link: " + link.toString())
    sql"insert into links (title,url,publication_date,feed_id) values (${link.getTitle},${link.getUrl},${link.getPublicationDate},${link.getFeed.getId})"
        .update
        .run
        .transact(transactor)
}

调用它的方法是:

    val links = for{
        feeds <- getFeeds()
        ls: List[Link] = feeds.flatMap(rssFeedReader.readFeedItems(_).asScala)
        
        ios = ls.map(
            link => 
                linkPersistence
                    .countByUrl(link.getUrl())
                    .map(x => if(x==0) linkPersistence.insert(link) else identity(x))
            
        )

        s <- ios.sequence
    }yield(s)
    val result = links.unsafeRunSync()
    logger.info("Result: " + result.toString())

不幸的是,我不能使用 For Expressions,因为 IO 没有 withFilter 并且我在 Maven 项目中(我正在将 Spring 引导应用程序迁移到 Typelevel 堆栈), 所以我不能使用改进的 For Expressions sbt 插件。

我的问题是行没有插入到数据库中。 日志上有:

reddit_bot_1  | 2021-04-23 13:06:57.805  INFO 1 --- [text-global-167] r.i.repository.LinkPersistence           : Inserting link: Link{id=0, feed=Feed{id=79, url='https://ytali.com/feed/'}, title='Se il grillo non fosse stato parlante', url='https://ytali.com/2021/04/21/se-il-grillo-non-fosse-stato-parlante/', publicationDate=Wed Apr 21 11:12:59 GMT 2021}
reddit_bot_1  | 2021-04-23 13:06:57.838  INFO 1 --- [text-global-167] r.i.repository.LinkPersistence           : Inserting link: Link{id=0, feed=Feed{id=82, url='https://cronacheletterarie.com/feed/'}, title='Scrivere come in una serie tv', url='https://www.cronacheletterarie.com/2021/04/22/scrivere-come-in-una-serie-tv-due-nuovi-thriller-italiani/', publicationDate=Thu Apr 22 06:50:30 GMT 2021}
reddit_bot_1  | 2021-04-23 13:06:57.993  INFO 1 --- [nio-8080-exec-1] reddit_bot.service.LinkUpdater           : Result: List(1, 1, 1, 1, 1, 1, 1, IO0148716, IO8844220, IO51359159, IO02460161, IO46104176, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, IO25243662, 1, 1, 1, 1, 1, 1, 1, 1, 1, IO3629085, IO57291647, IO62915922, IO86018284, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, IO29671523, IO03036679, IO23891149, IO90799695, IO9359223, IO89070694, IO2184845, IO8827115, IO23402242, IO63752499, IO62614371, IO82901634, IO92599455, IO61386362, IO2495060, IO71010351, IO5298961, IO95689700, IO22084533, IO4291117, IO7707631, IO35432555, IO4428575, IO8145293, IO14815708, IO54086426, IO74886515, IO48606753, IO1801989, IO29261832, IO40654268, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, IO96825326, IO32380347, IO4110340, IO4966863, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, IO29149648, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, IO24908444, IO35403239, IO33511951, IO85617069, IO6405632, IO73704159, IO78164304, IO4307019, IO04298152, 1, IO26495986, 1, 1, 1, 1, 1, 1, 1, 1, 1)

事务处理程序是这样创建的:

def transactor() = Transactor.fromDriverManager[IO](
  "com.mysql.cj.jdbc.Driver",
  "jdbc:mysql://database:3306/redditbot",
  "redditbot",
  "redditbot"
)

更新

根据@luis-miguel-mejía-suárez 的建议,我修改了 pom.xml 文件,如下所示:

         <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>4.4.1</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <scalaVersion>${scala.version}</scalaVersion>
                <sourceDir>src/main/scala</sourceDir>
                <compilerPlugins>
                    <compilerPlugin>
                        <groupId>com.olegpy</groupId>
                        <artifactId>better-monadic-for_2.13</artifactId>
                        <version>0.3.1</version>
                    </compilerPlugin>
                </compilerPlugins>
            </configuration>
        </plugin>

但问题依旧。

由@LuisMiguelMejíaSuárez 撰写

As the error clearly says, IO does not have a withFilter method. (You can check the scaladoc here). When you put the type explicitly, you are basically filtering all elements that match such type. And, since the method does not exists, it won't compile. - And no, I do not know any workaround.

But, I can think on at least ne reason of why it should not have it. IO is not exactly a "container" of elements, like List, since it only is a description of a computation, and if you ant to see it like a container it will only had one element, like Option. But, unlike the former, there is not concept of empty IO. Thus, filtering an IO would not make sense.

我找到的解决方法是将过滤器移到另一个函数中:

def insertIfNotPresent(link: Link, foundLinksCount: Int): IO[Option[Int]] = 
    foundLinksCount match{
        case 0 => linkPersistence.insert(link).map(Option(_))
        case _ => IO.pure(None)
    }

调用代码变为:

for{
  foundLinksCount: Int <- linkPersistence.countByUrl(link.getUrl())
  n: Option[Int] <- insertIfNotPresent(link, foundLinksCount)
}yield(n)