Java 如果将自定义查询与联接一起使用,则Hibernate AttributeConverter将失败

Java 如果将自定义查询与联接一起使用,则Hibernate AttributeConverter将失败,java,hibernate,spring-data-jpa,hibernate-jpa,Java,Hibernate,Spring Data Jpa,Hibernate Jpa,我在HibernateJPA2.1中发现了非常有趣的bug。当我在存储库中编写自定义查询实现并在查询中同时使用自定义AttributeConverter和JOIN时,AttributeConverter不起作用。我确信,JOIN会导致这个问题,但我不知道如何解决它。在查询中不使用JOIN AttributeConverter可以正常工作。我发现了一个丑陋的解决方案(你可以在我的代码中看到),但我正在寻找正确的解决方案 因此,在使用JOIN进行查询的情况下 SELECT t FROM TaskEn

我在HibernateJPA2.1中发现了非常有趣的bug。当我在存储库中编写自定义查询实现并在查询中同时使用自定义AttributeConverter和JOIN时,AttributeConverter不起作用。我确信,JOIN会导致这个问题,但我不知道如何解决它。在查询中不使用JOIN AttributeConverter可以正常工作。我发现了一个丑陋的解决方案(你可以在我的代码中看到),但我正在寻找正确的解决方案

因此,在使用JOIN进行查询的情况下

SELECT t FROM TaskEntity t JOIN t.involvedUsers u WHERE status in :statuses AND u.id IN :involvedUserIds ORDER BY t.id DESC 
查询参数:

statuses = [CREATED, APPROVED, IN_PROGRESS];
involvedUserIds = [1, 2];
我得到了以下错误:

2018-02-26 15:39:36.458 DEBUG 2482 --- [nio-8008-exec-1] org.hibernate.SQL                        : select taskentity0_.id as id1_11_, taskentity0_.amount as amount2_11_, taskentity0_.comment as comment3_11_, taskentity0_.commission as commissi4_11_, taskentity0_.created as created5_11_, taskentity0_.currency as currency6_11_, taskentity0_.current_account_id as current14_11_, taskentity0_.current_object_id as current15_11_, taskentity0_.current_user_id as current16_11_, taskentity0_.description as descript7_11_, taskentity0_.data as data8_11_, taskentity0_.initiator_account_id as initiat17_11_, taskentity0_.initiator_object_id as initiat18_11_, taskentity0_.initiator_user_id as initiat19_11_, taskentity0_.payment_method as payment_9_11_, taskentity0_.status as status10_11_, taskentity0_.title as title11_11_, taskentity0_.updated as updated12_11_, taskentity0_.version as version13_11_ from public.tasks taskentity0_ inner join public.tasks_users involvedus1_ on taskentity0_.id=involvedus1_.task_id inner join public.users userentity2_ on involvedus1_.user_id=userentity2_.id where (status in (? , ? , ?)) and (userentity2_.id in (? , ?)) order by taskentity0_.id DESC limit ?
2018-02-26 15:39:36.459 TRACE 2482 --- [nio-8008-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARBINARY] - [CREATED]
2018-02-26 15:39:36.460 TRACE 2482 --- [nio-8008-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARBINARY] - [APPROVED]
2018-02-26 15:39:36.460 TRACE 2482 --- [nio-8008-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARBINARY] - [IN_PROGRESS]
2018-02-26 15:39:36.460 TRACE 2482 --- [nio-8008-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [INTEGER] - [1]
2018-02-26 15:39:36.461 TRACE 2482 --- [nio-8008-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [INTEGER] - [2]

org.postgresql.util.PSQLException: ERROR: operator does not exist: integer = bytea
  No operator matches the given name and argument type(s). You might need to add explicit type casts.
代码如下:

@Repository
public class TaskRepositoryImpl implements CustomTaskRepository {

    private final EntityManager em;


    @Autowired
    public TaskRepositoryImpl(JpaContext context) {
        this.em = context.getEntityManagerByManagedType(TaskEntity.class);
    }
    public List<TaskEntity> find(List<TaskStatuses> statuses, List<Integer> involvedUserIds) {
        Map<String, Object> params = new HashMap<>();
        StringBuilder queryStr = new StringBuilder("SELECT t FROM TaskEntity t WHERE");

        if (statuses != null && !statuses.isEmpty()) {
            queryStr.append(" status in :statuses AND");
            params.put("statuses", involvedUserIds == null ? statuses :
                statuses.stream().map(TaskStatuses::getId).collect(Collectors.toList())); //problem is here
        }
        if (involvedUserIds != null && !involvedUserIds.isEmpty()) {
            queryStr.insert(queryStr.indexOf("WHERE"), "JOIN t.involvedUsers u "); //this join causes the problem
            queryStr.append(" u.id IN :involvedUserIds AND");
            params.put("involvedUserIds", involvedUserIds);
        }
        if (queryStr.lastIndexOf(" WHERE") == queryStr.length() - 6)
            queryStr.setLength(queryStr.length() - 6);
        else
            queryStr.setLength(queryStr.length() - 4);
        Query query = em.createQuery(queryStr.toString());
        params.forEach(query::setParameter);
        query.setFirstResult(0);
        query.setMaxResults(20);
        return query.getResultList();
    }
}
任务状态:

public enum TaskStatuses {
    CREATED(1),
    APPROVED(2),
    IN_PROGRESS(3),
    COMPLETED(4),

    REJECTED(100),
    ;

    private Integer id;

    TaskStatuses(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public static TaskStatuses valueOf(Integer id) {
        for (TaskStatuses value : values())
            if (value.getId().equals(id))
                return value;
        return null;
    }
}
任务状态转换器:

public class TaskStatusesConverter implements AttributeConverter<TaskStatuses, Integer> {

    @Override
    public Integer convertToDatabaseColumn(TaskStatuses status) {
        return status.getId();
    }

    @Override
    public TaskStatuses convertToEntityAttribute(Integer status) {
        return TaskStatuses.valueOf(status);
    }
}
公共类TaskStatuseConverter实现AttributeConverter{
@凌驾
公共整数convertToDatabaseColumn(任务状态){
返回status.getId();
}
@凌驾
公共任务状态convertToEntityAttribute(整数状态){
返回任务状态。值(状态);
}
}
和存储库:

@NoRepositoryBean
public interface CustomTaskRepository {
    List<TaskEntity> find(List<TaskStatuses> statuses, List<Integer> involvedUserIds)
}
@NoRepositoryBean
公共接口CustomTaskRepository{
列表查找(列表状态、列表涉及的数据项)
}
在这个项目中,我使用的是
springboot1.5.8.RELEASE
springdatajpa1.5.8.RELEASE
。来自project的代码简化了,只包含本示例所需的信息(您可以在日志中看到一些冗余信息)。谢谢你的帮助

试试这个:

select t from TaskEntity t where t.status in (:statuses) and t.involvedUsers.id in (:involvedUserIds) order by t.id DESC

我有以下错误,我只看到调试和跟踪消息,没有错误谢谢。问题更新可能
状态
应该是
t.status
?因为它不合格,我使用的是
:statuses
qualifier”params.put(“statuses”,involvedUserIds==null?statuses:statuses.stream().map(TaskStatuses::getId).collect(Collectors.toList());“在我看来是非常可疑的,因为当involvedUserIds为null时,您使用List,但当involvedUserIds为null时,您使用List。这不可能是对的,在这两种情况下都应该是一个列表。
@NoRepositoryBean
public interface CustomTaskRepository {
    List<TaskEntity> find(List<TaskStatuses> statuses, List<Integer> involvedUserIds)
}
select t from TaskEntity t where t.status in (:statuses) and t.involvedUsers.id in (:involvedUserIds) order by t.id DESC