blinkfox / blinkfox.github.io

This is my personal blog repository.
https://blinkfox.github.io/
Apache License 2.0
45 stars 101 forks source link

Fenix — 比 MyBatis 更加强大的 Spring Data JPA 扩展库 | 闪烁之狐 #80

Open blinkfox opened 4 years ago

blinkfox commented 4 years ago

https://blinkfox.github.io/2019/08/20/hou-duan/jpa/fenix-bi-mybatis-geng-jia-qiang-da-de-spring-data-jpa-kuo-zhan-ku/

Fenix(菲尼克斯)是一个比 MyBatis 更加强大,为解决复杂、动态 SQL (JPQL) 而生的 Spring Data JPA 扩展库,目的是辅助开发者更方便、快捷的书写复杂、动态且易于维护的 SQL,支持 XML 和 Java

azhengZJ commented 4 years ago

spring-data-jpa使用多年,自己也写了一些很实用的组件,难得看到有jpa的扩展库,使用下来感觉非常赞,唯一不足的就是不能动态映射,不能自定义实体类(VO/DTO)返回。这样就不能select自己想要的,对于稍微复杂select的sql支持不是很好。望改进,加油 !!!

blinkfox commented 4 years ago

@azhengZJ JPA 里面是可以将查询结果映射为自定义实体类的,你可以了解下 JPA 投影(Projection)的用法,功能也比较强大。Fenix 的核心扩展点在动态 SQL 的支持,所以,投影也是支持的。

azhengZJ commented 4 years ago

@blinkfox 正是因为使用了Projections未生效,所以在此留言,但是未用fenix的xml文件的动态投影都生效了,也可能是我用法不对,我继续研究研究!

azhengZJ commented 4 years ago

@blinkfox 各种方式都尝试了,确实不支持,如果支持的话,希望能提供一下文档,感谢!

blinkfox commented 4 years ago

@azhengZJ 我自己测试就是支持的,不晓得你的为啥不行,或者有报什么错之类的,发出来我看看。

azhengZJ commented 4 years ago

@blinkfox

这是定义接口的地方

@QueryFenix
List<FenixVO> queryByXML(@Param("params") ReqMailMessageVO params);

这是xml

    <fenix id="queryByXML" removeIfExist="1 = 1 AND ">
        SELECT
            a.id,
            a.content
        FROM
            MailMessage AS a
        WHERE
            1 = 1
        <andLike field="a.content" value="params.content" match="params.content != empty"/>
    </fenix>

这是调用的地方

List<FenixVO> list = repository.queryByXML(vo);

这是返回的VO

import lombok.Value;

@Value
public class FenixVO {
    private Long id;
    private String content;
}

报错如下

Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Long] to type [com.zuji.msgdemo.entity.vo.FenixVO]
blinkfox commented 4 years ago

@azhengZJ 你这个不是投影的用法吧,投影的话,你需要自己定义一个接口,接口中的方法其实就对应着你自定义 Bean 里面的 Getter 方法,当然还可以增加其他扩展或者需要预处理的方法。你可以参看我单元测试里面的 queryUserBlogsByProjection 方法的写法:

-BlogRepositoryTest -BlogRepository -UserBlogProjectio

除了使用投影的方式之外,你的示例场景,可以直接在你的实体类中,定义一个只有这两个值的构造方法,用 select new MailMessage(id, content) 的方式也行。

azhengZJ commented 4 years ago

@blinkfox 投影的类型可以是接口也可以是类。 基于接口的投影,须提供字段对应的get方法接口。

interface NamesQueryDTO {

  String getFirstname();
  String getLastname();

}

基于类的投影,定义好所有查询字段,并且提供全参构造器。强烈推荐 使用Lombok的@Value注解 简化代码。

@Value
class NamesOnlyDTO {
    String firstname, lastname;
}
azhengZJ commented 4 years ago

https://blog.csdn.net/qq_41959009/article/details/101363309 之前写过相关博客,定义成接口也没关系,只要支持就行,通常还是使用类更方便。

azhengZJ commented 4 years ago

测试了一下 ,对接口确实是支持的,对类的方式还是不支持,new对象的方式我也知道,这种方式我不太喜欢用,因为需要创建对应的构造方法,而且构造方法和select字段的顺序有强一致性的要求,这个就增加了开发难度,而且后期构造方法或者select字段顺序不小心被改动都会影响到它的正常执行。不过能支持接口已经满足我的需求,感谢!

blinkfox commented 4 years ago

@azhengZJ 也是支持类的,就在刚才的的几个单元测试文件中,有类的情况,单测方法为:queryUserBlogsByTitleWithFenix,其中的 XML 写法在 BlogRepository.xml 文件中,fenixId 为 queryUserBlogsByTitleWithFenix,JPA 里面自定义的类是必须要用 new 和对应的构造方法的方式才行。

要想只通过字段名字来对应,不用写 new 的话,除非想办法做成 MyBatis 里面那样,XML 中定义一个 ResultMap,对应具体的实体类,将各个结果字段通过反射的 Setter 方法来注入到结果对象中才行,JPA 里面是不行的。

Fenix 目前的 SQL 执行都是使用 JPA 自身提供的,没有做过额外处理。

azhengZJ commented 4 years ago

@blinkfox 好的 ,理解的,感谢!

blinkfox commented 4 years ago

@azhengZJ Fenix v1.1.0 版本支持返回自定义实体对象了,这是使用使用示例

azhengZJ commented 4 years ago

@blinkfox :thumbsup: 效率非常高,这个功能很实用。

deepthan commented 4 years ago

o

chenxinshinian commented 4 years ago

博主,我发现一个bug,苹果safari浏览器浏览显示的文章访问次数不对