2013-10-14 1 views
2

У меня есть два объекта JPA: VirtualLot и VirtualFiles. VirtualFiles распространяется VirtualInode. Существует ManyToMany соотношение между VirtualLot и VirtualFiles описывается как «А VirtualLot может содержать VirtualFiles» и «А VirtualFile может быть связан с несколькими VirtualLots» Объекты определяются следующим образом:Как использовать «размер» в качестве имени поля в сущности hibernate/jpa?

VirtualFile.java

@Entity 
@Table(name = "FIL_FILE") 
public class VirtualFile extends VirtualInode { 
    //[...] 
} 

VirtualInode.java

@Entity 
@Table(name = "INO_INODE") 
@Inheritance(strategy = InheritanceType.JOINED) 
public class VirtualInode implements Serializable { 
    private Long id; /* The PK */ 
    private long size = 0L; /* The size */ 
    // [...] 

    /** 
    * Default constructor 
    */ 
    public VirtualInode() { 
     super(); 
    } 

    /** 
    * @return the id 
    */ 
    @Id 
    @Column(name = "INO_ID", nullable = false) 
    public Long getId() { 
     return id; 
    } 

    /** 
    * @return the size 
    */ 
    @Column(name = "INO_SIZE", nullable = false) 
    public long getSize() { 
     return size; 
    } 

    //[...] 
} 

VirtualLot.java

@Entity 
@Table(name = "VLT_VIRTUAL_LOT") 
public class VirtualLot implements Serializable { 
    private Long id; /* The PK */ 
    private Collection<VirtualFile> files; 

    /** 
    * Default constructor 
    */ 
    public VirtualLot() { 
     super(); 
    } 

    /** 
    * @return the id 
    */ 
    @Id 
    @Column(name = "VLT_ID", nullable = false) 
    public Long getId() { 
     return id; 
    } 


    /** 
    * @return the files 
    */ 
    @ManyToMany 
    @JoinTable(name = "R001_FIL_VLT", joinColumns = @JoinColumn(name = "VLT_ID", referencedColumnName = "VLT_ID"), inverseJoinColumns = @JoinColumn(name = "INO_ID", referencedColumnName = "INO_ID")) 
    public Collection<VirtualFile> getFiles() { 
     return files; 
    } 
    //[...] 
} 

Здесь я хочу подвести размер VirtualFiles, содержащихся в данном VirtualLot используя репозиторий Spring Data JPA: VirtualLotRepository. Запрос определяется следующим образом:

public interface VirtualLotRepository extends JpaRepository<VirtualLot, Long> 
{ 
    @Query("select sum(f.size) from VirtualLot l join l.files f where l.id = ?1") 
    long sumFilesSize(long lotId); 
} 

Моя проблема заключается в том, что Hibernate/JPA напутает с «размер» ключевое слово, он интерпретирует его как функцию SIZE, определяемой спящего режима (http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch11.html#ql-collection-expressions)

результате запрос был :

select 
     sum((select 
      count(virtualfil2_.VLT_ID) 
     from 
      R001_FIL_VLT files1_, 
      FIL_FILE virtualfil2_ 
     inner join 
      INO_INODE virtualfil2_1_ 
       on virtualfil2_.INO_ID=virtualfil2_1_.INO_ID 
     where 
      virtuallot0_.VLT_ID=files1_.VLT_ID 
      and files1_.INO_ID=virtualfil2_.INO_ID)) as col_0_0_ 
    from 
     VLT_VIRTUAL_LOT virtuallot0_ 
    inner join 
     R001_FIL_VLT files1_ 
      on virtuallot0_.VLT_ID=files1_.VLT_ID 
    inner join 
     FIL_FILE virtualfil2_ 
      on files1_.INO_ID=virtualfil2_.INO_ID 
    inner join 
     INO_INODE virtualfil2_1_ 
      on virtualfil2_.INO_ID=virtualfil2_1_.INO_ID 
    where 
     virtuallot0_.VLT_ID=? 

который (очевидно) не работает. Я хочу, чтобы это было так:

select 
     sum(virtualfil2_1_.INO_SIZE) 
    from 
     VLT_VIRTUAL_LOT virtuallot0_ 
    inner join 
     R001_FIL_VLT files1_ 
      on virtuallot0_.VLT_ID=files1_.VLT_ID 
    inner join 
     FIL_FILE virtualfil2_ 
      on files1_.INO_ID=virtualfil2_.INO_ID 
    inner join 
     INO_INODE virtualfil2_1_ 
      on virtualfil2_.INO_ID=virtualfil2_1_.INO_ID 
    where 
     virtuallot0_.VLT_ID=? 

Который работает в моей SQL блокнота (с подходящим значением «?»).

Можно ли сообщить Hibernate/JPA, что размер является свойством размера моего объекта VirtualInode/VirtualFile, а не функцией SIZE?

Я уже пробовал сбрасывать двойные кавычки, и это не работает. Я использую диалект Oracle10g.

EDIT: Если добавить дубликат свойства fsize моей VirtualInode сущности и использовать его в моей просьбе, она работает, но это не решение, которое я ищу.

VirtualInode.java

@Column(name = "INO_SIZE", nullable = false, updatable = false, insertable = false) 
public long getFsize() { 
    return getSize(); 
} 

public void setFsize(final long size) { 
    setSize(size); 
} 

VirtualLotRepository.java

@Query("select sum(f.fsize) from VirtualLot l join l.files f where l.id = ?1") 
long sumFilesSize(long lotId); 
+1

измените поле своего размера на другое имя и скажите, что произойдет. –

+0

Это работает, но это не то решение, которое я ищу, спасибо в любом случае – superbob

ответ

2

size - зарезервированное ключевое слово, такое как default или for в Java. Поэтому либо измените свое имя для своей переменной в perhabs nodeSize, либо используйте атрибут @Column(name = "nodeSize") с атрибутом name, чтобы дать основному столбцу специальное имя.

+0

Возможно ли иметь обходное решение, например, предлагаемое здесь решение? http://stackoverflow.com/questions/3462477/jpa-weird-error-when-i-try-to-persist-an-object#answer-3463241 – superbob

+0

Я полностью забываю об этом. Я обновил свой ответ. –

+0

Спецификации JPA 2 явно запрещают использование зарезервированных ключевых слов в запросах (JPA2 - 4.4.1 Идентификаторы), но не запрещают их в именах объектов и свойств (JPA2 - 2.13 Именование объектов базы данных). Это вызывает беспокойство и разочарование, когда есть такие ограничения, особенно с использованием подхода MDD ... – superbob

1

Я не уверен в этом решении, но попробовать:

Просто изменить свой @Query, используя следующие:

@Query(value = "select sum(f.size) from VirtualLot l join l.files f where l.id = ?1", nativeQuery = true) 

Параметр nativeQuery должен изменить ваш запрос в исходный запрос Oracle.

См. this stackoverflow topic и ссылки, представленные здесь в качестве ссылки.

Надеюсь, что это исправит вашу проблему.