JPA NamedQuery с Join возвращает пустой список

Я борюсь с namedquery в течение нескольких дней. Именованный запрос имеет внутреннее соединение со 2-й таблицей. Одна из дополнительных сложностей заключается в том, что первичный ключ на 2-й таблице является составным ключом. У меня есть две упрощенные таблицы здесь:

Table: aname
nameIdx  number(9),
firstName  varchar2(40),
lastName  varchar2(40),

первичный ключ nameIdx

Table: aname_role
nameIdx number(9), --foreign key to name table
nameType  char(2),
inactiveFlag char(1)

составной первичный ключ находится на nameIdx и nameType

Я пытаюсь эмулировать следующий sql-запрос в JPQL:

select * from aname n 
   left join aname_role nr on n.nameidx=nr.nameidx
where nr.nametype='5' 
   and nr.inactiveflag='N';

Этот запрос работает так, как ожидалось в Oracle, возвращающем много записей. В Java у меня есть эти сущности JPA:

@Entity
@Table(name="ANAME")
@NamedQueries({
  @NamedQuery(name = "AName.findActiveSalesPersons", query = "SELECT a FROM AName a LEFT JOIN a.aNameRoleList r WHERE r.inactiveflag='N' and r.ANameRolePK.nametype='5' ")})
public class AName implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "NAMEIDX")
    private Integer nameidx;
    @Column(name = "FIRSTNAME")
    private String firstname;
    @Column(name = "LASTNAME")
    private String lastname;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "aName")
    private List<ANameRole> aNameRoleList;
    //getters and setters here

и

@Entity
@Table(name = "ANAME_ROLE")
public class ANameRole implements Serializable {

    private static final long serialVersionUID = 1L;
    @EmbeddedId
    protected ANameRolePK aNameRolePK;
    @Basic(optional = false)
    @NotNull
    @Column(name = "INACTIVEFLAG")
    private Character inactiveflag;
    @JoinColumn(name = "NAMEIDX", referencedColumnName = "NAMEIDX", insertable = false, updatable = false)
    @ManyToOne(optional = false)
    private AName aName;
    //getters and setters here

Существует также класс первичного ключа ANameRolePK

@Embeddable
public class ANameRolePK implements Serializable {

    @Basic(optional = false)
    @NotNull
    @Column(name = "NAMEIDX")
    private int nameidx;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 2)
    @Column(name = "NAMETYPE")
    private String nametype;
    //getters and setters here

При этой настройке, включая именованный запрос, указанный в сущности AName выше, следующий возвращает пустой список результатов:

em.createNamedQuery("AName.findActiveSalesPersons").getResultList();

Может ли кто-нибудь указать мне, что я делаю неправильно в этом именованном запросе?

SELECT a FROM AName a LEFT JOIN a.aNameRoleList r WHERE r.inactiveflag='N' and r.aNameRolePK.nametype='5'

Спасибо,

Стив

2 ответа

  1. По умолчанию, по крайней мере , с помощью Hibernate, тип выборки по умолчаниюLazy, поэтому вам нужно сделать join fetchвместо a join. Кроме того, вы должны были select distinct. Пытаться:

    SELECT distinct a FROM AName a LEFT JOIN fetch a.aNameRoleList r WHERE r.inactiveflag='N' and r.aNameRolePK.nametype='5'
    

    Ссылки: тип выборки по умолчанию для one-to-one, many-to-one и one-to-many в спящем режиме

  2. После дополнительного тестирования я понял, что соединение работает, но не «r.aNameRolePK.nametype= ‘5’». Но если бы я изменил это на » r.aNameRolePK.nameidx=1 » работает. Таким образом, это было просто поле nametype, которое мы определили как char(2) в базе данных. Проблема с пространствами в поле char, и это обсуждается здесь: проблема строки Java NamedQuery . Похоже, что рекомендуемый способ решить эту проблему-реализовать Eclipselink SessionCustomizer. Для тестирования я изменил именованный запрос на

    SELECT a 
    FROM AName a LEFT JOIN a.aNameRoleList r 
    WHERE r.inactiveflag='N' and trim(trailing from r.aNameRolePK.nametype)=5
    

    Это возвращает ожидаемые записи.