Spring Boot,Hibernate,Querydsl:antlr.NoViableAltException:意外令牌

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot,Hibernate,Querydsl:antlr.NoViableAltException:意外令牌相关的知识,希望对你有一定的参考价值。

我目前正在使用Spring Boot,Hibernate和querydsl开发数据仓库。几乎一切都工作正常,但是我无法对我的一个实体group进行搜索请求。错误,并没有真正的帮助:

我的请求很简单/group/advancedSearch?page=0&size=10&sort=name,asc&search=groupCode:dfa,name:dfa,

当我调用存储库方法时,错误会在我的服务中引发。

antlr.NoViableAltException: unexpected token: group
[...]
java.lang.NullPointerException: null

为了使它更容易理解,我的代码如下。我对大多数实体都使用相同的方法,并且工作正常。因为我不知道unexpected token group可能来自何处,所以我查看了生成的类QGroup,在那里我发现了代码public static final QGroup group = new QGroup("group1");的这种平静。名称group1让我感到奇怪,但是我不确定是否与错误有关。在所有其他类中,字符串始终是带有小写字母的类的名称。

我以为实体group可能是重复的,所以querydsl将创建groupgroup1,但事实并非如此。因此,有什么想法可能会导致错误,以及如何防止/修复错误?

实体:

@Entity
@Table(name = "[Group]")
public class Group {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Group_ID")
    private long groupId;

    @ManyToOne()
    @JoinColumn(name = "Dimension_ID")
    private Dimension dimension;

    @Column(name = "Dimension_ID", updatable = false, insertable = false)
    private Long dimensionId;

    @Column(name = "GroupCode")
    private String groupCode;

    @Column(name = "Name")
    private String name;

    [...]
}

出现错误的控制器功能:

    @RequestMapping(value = GROUP_URL + "/advancedSearch", method = RequestMethod.GET)
    @ResponseBody
    public PagedResources<Group> advancedSearch(
            @RequestParam(value = "search", required = false) String search,
            Pageable pageable, @RequestParam MultiValueMap<String, String> parameters,
            PersistentEntityResourceAssembler persistentEntityResourceAssembler
    ) {
        SimpleGrantedAuthority[] allowedRoles = {SYSADMIN};
        GeneralPredicateBuilder<Group> builder = new GeneralPredicateBuilder<>(Group.class);
        Predicate predicate = predicateService.getPredicateFromParameters(parameters, Group.class);
        Page<Group> results = service.advancedSearch(
                this.buildAdvancedSearch(search, predicate, builder), pageable, allowedRoles);
        return super.toPagedResource(results, persistentEntityResourceAssembler);
    }

    public Predicate buildAdvancedSearch(String search, Predicate predicate, GeneralPredicateBuilder<T> builder) {
        if (search != null) {
            Pattern pattern = Pattern.compile("(\w+?)(:|<|>)(\w+?),");
            Matcher matcher = pattern.matcher(search + ",");
            while (matcher.find()) {
                builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
            }
            BooleanExpression expression = builder.build();
            if (predicate != null) {
                predicate = expression.and(predicate);
            } else {
                predicate = expression;
            }
        }
        return predicate;
    }

PredicateService

@Service
public class PredicateService {

    @Autowired
    private final QuerydslPredicateBuilder querydslPredicateBuilder;

    @Autowired
    private final QuerydslBindingsFactory querydslBindingsFactory;

    public PredicateService(QuerydslPredicateBuilder querydslPredicateBuilder, QuerydslBindingsFactory querydslBindingsFactory) {
        this.querydslPredicateBuilder = querydslPredicateBuilder;
        this.querydslBindingsFactory = querydslBindingsFactory;
    }

    public <T> Predicate getPredicateFromParameters(final MultiValueMap<String, String> parameters, Class<T> tClass) {
        TypeInformation<T> typeInformation = ClassTypeInformation.from(tClass);
        return querydslPredicateBuilder.getPredicate(typeInformation, parameters, querydslBindingsFactory.createBindingsFor(typeInformation));
    }
}

服务方法:

    public Page<Group> advancedSearch(Predicate predicate, Pageable pageable, SimpleGrantedAuthority[] roles){
        if (SecurityUtils.userHasAnyRole(roles)) {
            return this.repository.findAll(predicate, pageable); // <-- here the errors raise
        } else throw new ForbiddenException(FORBIDDEN);
    }

存储库:

@RepositoryRestResource(collectionResourceRel = GROUP_URL, path = GROUP_URL)
@CrossOrigin(exposedHeaders = "Access-Control-Allow-Origin")
public interface GroupRepository extends PagingAndSortingRepository<Group, Long>, JpaSpecificationExecutor<Group>, QuerydslPredicateExecutor<Group> {
}

由querydsl生成的类QGroup

@Generated("com.querydsl.codegen.EntitySerializer")
public class QGroup extends EntityPathBase<Group> {

    private static final long serialVersionUID = 384278695L;

    private static final PathInits INITS = PathInits.DIRECT2;

    public static final QGroup group = new QGroup("group1"); // <-- this is confusing

    [...]

更新

我终于找到了生成的查询:

select group1
from Group group1
where ?1 = ?1 and lower(group.groupCode) like ?2 escape '!'

我认为这是问题所在。在SQL开发人员视图中,group.groupCode应该为group1.groupCode。有人知道如何解决此问题吗?


更新2 [2020-02-14]:

GeneralPredicateBuilder:

public class GeneralPredicateBuilder<T> {
    private List<SearchCriteria> params;
    private final Class<T> type;


    public GeneralPredicateBuilder(Class<T> type) {
        this.params = new ArrayList<>();
        this.type = type;
    }

    public GeneralPredicateBuilder<T> with(String key, String operation, Object value) {
        params.add(new SearchCriteria(key, operation, value));
        return this;
    }

    public BooleanExpression build() {
        if (params.size() == 0) {
            return null;
        }

        List<BooleanExpression> predicates = params.stream().map(param -> {
            GeneralPredicate<T> predicate = new GeneralPredicate<T>(param, type);
            BooleanExpression tmp = predicate.getPredicate();
            return tmp;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        BooleanExpression result = Expressions.asBoolean(true).isTrue();
        for (BooleanExpression predicate : predicates) {
            result = result.and(predicate);
        }
        return result;
    }

    public List<Predicate> buildPredicate(){
        if (params.size() == 0) {
            return null;
        }

        return params.stream().map(param -> {
            GeneralPredicate<T> predicate = new GeneralPredicate<>(param, type);
            return predicate.getPredicate();
        }).filter(Objects::isNull).collect(Collectors.toList());
    }
}
答案
public class GeneralPredicate<T> { private SearchCriteria searchCriteria; private final Class<T> type; private final String variable; public GeneralPredicate(SearchCriteria param, Class<T> type) { searchCriteria = param; this.type = type; if(type.getSimpleName().equals("Group")){ this.variable = "group1"; } else { this.variable = type.getSimpleName().replaceFirst("" + type.getSimpleName().charAt(0), "" + type.getSimpleName().charAt(0)).toLowerCase(); } } public BooleanExpression getPredicate() { PathBuilder<T> entityPath = new PathBuilder<T>(type, variable); if (isNumeric(searchCriteria.getValue().toString())) { NumberPath<Integer> path = entityPath.getNumber(searchCriteria.getKey(), Integer.class); int value = Integer.parseInt(searchCriteria.getValue().toString()); switch (searchCriteria.getOperation()) { case ":": return path.eq(value); case ">": return path.goe(value); case "<": return path.loe(value); } } else { StringPath path = entityPath.getString(searchCriteria.getKey()); switch (searchCriteria.getOperation()) { case ":": return path.containsIgnoreCase(searchCriteria.getValue().toString()); case "<": return path.startsWith(searchCriteria.getValue().toString()); case ">": return path.endsWith(searchCriteria.getValue().toString()); } } return null; } }

您会在构造函数中找到脏修补程序。我真的很讨厌它,但是它正在运行,并且生成的sql正在运行。

也许我以错误的方式使用了通用名称。我愿意征求意见。

以上是关于Spring Boot,Hibernate,Querydsl:antlr.NoViableAltException:意外令牌的主要内容,如果未能解决你的问题,请参考以下文章

spring boot 集成 jpa+hibernate+jdbcTemplate

Spring boot/Hibernate 创建表失败

Spring Boot JPA Hibernate - 以毫秒精度存储日期

spring boot DAO之Hibernate

制作多个 EntityManager(Spring-Boot-JPA、Hibernate、MSSQL)

Spring Boot ManyToMany - *** - JPA,Hibernate