2017-11-20 18 views
-1

おはよう、 私はビジネスのためのインジケータに続くアプリケーションを開発しています。データベースはめったに構築されていないので、複雑なクエリ(私のレベルで)と複雑なマッピングが発生します。期待通りに動作し、クラスキャスト例外 - Hibernateマッピング+ Spring MVC

Caused by: java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to fr.alteca.outilindicateurs.entityRedmine.Issues 
at fr.alteca.outilindicateurs.controller.IssuesRESTController.init(IssuesRESTController.java:68) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:498) 
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:365) 
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:310) 
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133) 
... 44 more 

データベースクエリ(MySQLの):あなたは、次のスタックトレースに私の手をお願いすることができます

SELECT issues.id, 
max(CASE WHEN custom_fields.name='Date de résolution' 
    THEN custom_values.value 
ELSE '-' 
END) AS date_resolution , 
max(CASE WHEN custom_fields.name='Date d\'ouverture' 
    THEN custom_values.value 
ELSE '-' 
END) AS date_ouverture 
    FROM redmine_tma_ibp.issues 
join custom_values 
    on issues.id = custom_values.customized_id 
join custom_fields 
    on custom_values.custom_field_id = custom_fields.id 
join enumerations 
    on enumerations.id=issues.priority_id 

where (enumerations.type="IssuePriority" and (enumerations.position=1 or enumerations.position=2)) 
    and (status_id=3 or status_id=5) 
    and (custom_fields.name = "Date d'ouverture" or custom_fields.name="Date de résolution") 
    and str_to_date(custom_values.value, '%d/%m/%Y %H:%i') > date('2016-01-01') 
    group by issues.id 
この要求の

HQL翻訳(チェックアウトする):

public static String GET_RECORDS_FOR_M1 = 
     "Select i, max(case when cf.name=:date_denom then cv.value else null end) as date_ouverture FROM Issues i, CustomValues cv, CustomFields cf, Enumerations e " 
+  "join fetch i.values " 
+  "where i.id=cv.issue " 
+  "and cv.customFields=cf.id " 
+  "and e.id=i.priority " 
+  "and (e.type=:priority and (e.position=:position1 or e.position=:position2)) " 
+  "and (i.issueStatus.id=:status1 or i.issueStatus.id=:status2) " 
+  "and cf.name = :date_denom " 
+  "and str_to_date(cv.value, :date_format) > date(:date_ouverture)" 
+  "and i.projects.name=:pole " 
//+  "and :value member of i.values " 
+  "group by i.id"; 

マイRESTConstroller:

@RestController 
@RequestMapping("/issues") 
public class IssuesRESTController extends GenericRestController<Issues> { 

private List<Issues> listeM1; 
private List<Issues> trashBin; 

@Autowired 
IssuesRepository issuesRepository; 

@Autowired 
DataM1Repository dataM1Repository; 

@Autowired 
AuteurRepository auteurRepository; 

@Autowired 
PoleRepository poleRepository; 

@Autowired 
public IssuesRESTController(IssuesRepository repository, DataM1Repository dataM1Repository, AuteurRepository auteurRepository, PoleRepository poleRepository) { 
    super(repository); 
} 

@PostConstruct 
public void init() { 
    Param.poles=new HashMap<>(); 
    int i=0; 
    for(String s : issuesRepository.getPolesNames()) { 
     Param.poles.put(i, s); 
     i++; 
    } 
    listeM1= new ArrayList<>(); 
    trashBin = new ArrayList<>(); 
    listeM1 = issuesRepository.getM1Issues(); 
    System.out.println(listeM1.size()+" Enregistrements récupérés dans la  variable listeM1"); 

    /** 
    * On regarde si les tuples remontés sont déjà présent dans la base, 
    * si oui, on les enlève de la liste à traiter. 
    */ 

    System.out.println(listeM1.get(0).toString()); 

    for(Issues issue : listeM1) { 
     for(DataM1 d : dataM1Repository.list()) { 

      if(issue.getId()==d.getId_ticket()) { 
       System.out.println("Ticket trouvé correspondant au tuple"+issue + "\n suppression du tuple de la liste à traiter"); 
       trashBin.add(issue); 
       }; 
     } 
    } 

    for (Issues issue : trashBin) { // on évite java-util concurrentmodificationexception 
     listeM1.remove(issue); 
    } 
    trashBin.clear(); 

    /** 
    * On crée les tickets manquants, les poles et les auteurs suivant le besoin 
    */ 
    for(Issues issue : listeM1) { 

     System.out.println("Création dans la table outil des tickets manquants"); 

      DataM1 ticket = new DataM1(); 
      ticket.setId(Integer.SIZE); 
      ticket.setId_ticket(issue.getId()); 

      System.out.println("*********\n Ticket : "+issue.getId()+"\n**********"); 
      System.out.println("Recherche l'auteur "+ issue.getAuthor().getLastname()+" "+issue.getAuthor().getFirstname()+" dans la base ..."); 
      System.out.println(issue.getValues()); 

      try { 
       Auteur a = auteurRepository.findbyName(issue.getAuthor().getLastname(), issue.getAuthor().getFirstname()); 
       System.out.println("Auteur trouvé :"+a.getNom() + " "+a.getPrenom()); 
       ticket.setAuteur(a); 

      }catch(NullPointerException e){ 
      System.out.println("Cet auteur n'est pas en base .. création ..."); 
      ticket.setAuteur(new Auteur(issue.getAuthor().getLastname(), issue.getAuthor().getFirstname())); 
      } 

      System.out.println("Recherche du pole "+issue.getProjects().getName()+" dans la base ..."); 

      try { 
       Pole p = poleRepository.findbyName(issue.getProjects().getName()); 
       System.out.println("Pole trouvé : "+p.getNom_pole()); 
       ticket.setPole(p); 
      }catch(NullPointerException e) { 
       System.out.println("Ce pole n'est pas en base... création..."); 
       ticket.setPole(new Pole(issue.getProjects().getName())); 
      } 


      System.out.println("Création du ticket..."); 
      dataM1Repository.create(ticket); 
      System.out.println("Ticket crée"); 


    } 

} 

@Override 
@RequestMapping("/all") 
public ResponseEntity<List<Issues>> list(){ 
    List<Issues> list = issuesRepository.getAll(); 
    return new ResponseEntity<List<Issues>> (list, HttpStatus.OK); 
} 

@RequestMapping("/M1/list") 
public ResponseEntity<List<Issues>> listM1(){ 
    List<Issues> list = issuesRepository.getM1Issues(); 
    return new ResponseEntity<List<Issues>> (list, HttpStatus.OK); 
} 

@RequestMapping("/M1/count") 
public ResponseEntity<Long> countM1(){ 
    Long nbIssues = issuesRepository.countM1Issues(); 
    return new ResponseEntity<Long>(nbIssues, HttpStatus.OK); 
} 

@RequestMapping("/M1/poles") // recherche la liste des poles dans la base 
public ResponseEntity<List<String>> getPolesNames(){ 
    List<String> poles = issuesRepository.getPolesNames(); 
    return new ResponseEntity<List<String>>(poles, HttpStatus.OK); 
} 

@RequestMapping("/M1/pole") 
public ResponseEntity<List<Issues>> getPoleByName(@RequestParam(value="pole") int polekey){ 
    List<Issues> poles = issuesRepository.getPoleByName(polekey); 



    return new ResponseEntity<List<Issues>>(poles, HttpStatus.OK); 
} 

@RequestMapping("/M1/pole/count") 
public ResponseEntity<Long> countPoleByName(@RequestParam(value="pole") int polekey){ 
    Long poles = issuesRepository.CountPoleByName(polekey); 
    return new ResponseEntity<Long>(poles, HttpStatus.OK); 
} 

@RequestMapping("/M1/pole/count/all") 
public ResponseEntity<HashMap<String, Long>> getAllInformationOnPoles(){ 
    HashMap<String, Long> tabl = new HashMap<>(); 
    int i=0; 
    for(String s :issuesRepository.getPolesNames()) { 
     tabl.put(Param.poles.get(i), issuesRepository.CountPoleByName(i)); 
     i++; 
    } 

    return new ResponseEntity<HashMap<String, Long>>(tabl, HttpStatus.OK); 
} 

@RequestMapping("/M1/pole/count/red") 
public ResponseEntity<HashMap<String, Long>> getAllRedInformationOnPoles(){ 
    HashMap<String, Long> tabl = new HashMap<>(); 
    int i=0; 
    for(String s :issuesRepository.getPolesNames()) { 
     tabl.put(Param.poles.get(i), issuesRepository.CountRedPoleByName(i)); 
     i++; 
    } 

    return new ResponseEntity<HashMap<String, Long>>(tabl, HttpStatus.OK); 
} 


@RequestMapping("/test/issue") 
public ResponseEntity<Issues> listIssueFields(@RequestParam(value="issue") int id_issue){ 
    Issues list = issuesRepository.getIssueById(id_issue); 
    return new ResponseEntity<Issues>(list, HttpStatus.OK); 
} 


} 

私のエンティティクラス:

@Entity 
@Table(name = "issues") 
public class Issues { 

public Issues() {} 

/* 
* Primary key 
*/ 
@Id 
@Column(name = "id", unique = true, nullable = false) 
private int id; 

/* 
* Foreign keys 
*/ 

@JoinColumn(name = "project_id") 
@ManyToOne(targetEntity = Projects.class) 
private Projects projects; 

@JoinColumn(name = "status_id") 
@ManyToOne(targetEntity = IssueStatuses.class) 
private IssueStatuses issueStatus; 

@JoinColumn(name = "author_id", referencedColumnName = "id") 
@ManyToOne(targetEntity = Users.class) 
private Users author; 

@JoinColumn(name = "priority_id") 
@ManyToOne(targetEntity = Enumerations.class) 
private Enumerations priority; 


/* 
* Fields 
*/ 
@Column(name = "subject", nullable = false) 
private String subject; 

@Column(name = "description", nullable = true) 
private String description; 






@OneToMany(mappedBy = "issue", targetEntity = CustomValues.class, fetch = FetchType.LAZY) 
private List<CustomValues> values; 

@Transient 
private Map<CustomFields, String> mapValeurs; 

@Transient 
private IssueStatuses status; 

//getters & setters 

マイリポジトリ:

@Repository 
public class IssuesRepository extends GenericCRUDImplRedmine<Issues>{ 

public IssuesRepository() { 
    super(); 
    System.out.println(Repositories.BUILD+this.getClass().getSimpleName()); 
} 

@SuppressWarnings("unchecked") 
public List<Issues> getAll() { 
    String sql = Database.GET_ALL_ISSUES; 
    return super.getCurrentSession().createQuery(sql).getResultList(); 
} 


@SuppressWarnings("unchecked") 
public List<Issues> getM1Issues(){ 
    String sql = Database.GET_RECORDS_FOR_M1; 
    System.out.println("requete : "+sql); 
    List<Issues> M1Issues =(List<Issues>) super.getCurrentSession().createQuery(sql) 
          .setParameter("priority", Param.priority) 
          .setParameter("position1", Param.position[0]) 
          .setParameter("position2", Param.position[1]) 
          .setParameter("status1", Param.status[0]) 
          .setParameter("status2", Param.status[1]) 
          .setParameter("date_ouverture", Date.date_ouverture) 
          .setParameter("date_resolution", Date.date_resolution) 
          .setParameter("date_format", Date.FORMAT_DATE_M1) 
          .setParameter("date_denom", Date.date_denom) 
          .setParameter("pole", Param.poles.get(0)) // define the key 
          //.setParameter("value", 1) 
          .getResultList(); 

    return M1Issues; 
} 

私の一般的なCRUD実装:

@Transactional("hibernateTransactionManagerRedmine") 

パブリッククラスGenericCRUDImplRedmineがGenericCRUD {

private final Class<T> persistentClass; 

@Autowired 
@Qualifier("sessionFactoryRedmine") 
private SessionFactory sessionFactory; 




protected Session getCurrentSession() { 
    boolean testSessionFactory = sessionFactory!=null; 
    System.out.println("Avons nous une sessionFactory? "+testSessionFactory); 

    Session session = sessionFactory.getCurrentSession(); 
    boolean testSession = session!=null; 
    System.out.println("Avons nous une session? "+testSession); 
    return session; 
} 

@SuppressWarnings("unchecked") 
public GenericCRUDImplRedmine() { 
    this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()) 
      .getActualTypeArguments()[0]; 
} 

@Override 
public void create(final T entity) { 
    this.getCurrentSession().save(entity); 
} 

@Override 
public void update(T t) { 
    this.getCurrentSession().update(t); 

} 

@Override 
public void refresh(T t) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void delete(Integer id) { 
    this.getCurrentSession().delete(this.find(id)); 

} 

@Override 
public T find(Integer id) { 
    // TODO Auto-generated method stub 
    return (T) this.getCurrentSession().get(persistentClass, id); 
} 

@SuppressWarnings("unchecked") 
@Override 
public List<T> list() { 
    // TODO Auto-generated method stub 
    return this.getCurrentSession().createQuery("from "+persistentClass).getResultList(); 
} 
を実装

DB設定:

@Configuration 
@EnableTransactionManagement 
public class DBConfig { 

/** 
* Créer la fabrique de session à la base de données et associe les entités 
* utilisables dans la session. 
* 
* @return SessionFactory 
*/ 
@Bean(name="sessionFactoryOutil") 
public SessionFactory sessionFactoryOutil() { 
    System.out.println("Construction de l'objet SessionFactory pour l'outil..."); 
    return new LocalSessionFactoryBuilder(getDataSourceOutil()) 
      .scanPackages("fr.alteca.outilindicateurs.entityOutil") 
      .buildSessionFactory(); 
} 

@Bean(name="sessionFactoryRedmine") 
public SessionFactory sessionFactoryRedmine() { 
    System.out.println("Construction de l'objet SessionFactory pour Redmine..."); 
    return new LocalSessionFactoryBuilder(getDataSourceRedmine()) 
      .scanPackages("fr.alteca.outilindicateurs.entityRedmine") 
      .buildSessionFactory(); 
} 

/** 
* Configure l'accès à la base de données. 
* La configuration à la base de données se trouve dans le fichier de contexte (WebContent/META-INF/context.xml) 
* 
* @return DataSource 
*/ 
@Bean(name="dataSourceOutil") 
public DataSource getDataSourceOutil() { 

    try { 
     InitialContext initialContext = new InitialContext(); 
     DataSource datasource = (DataSource) initialContext.lookup("java:/comp/env/jdbc/postgres"); 
     System.out.println("Base de donnée outil Localisée"); 
     return datasource; 

    } catch (NamingException e) { 
     e.printStackTrace(); 
     return null; 
    } 

} 

@Bean(name="dataSourceRedmine") 
public DataSource getDataSourceRedmine() { 

    try { 
     InitialContext initialContext = new InitialContext(); 
     DataSource datasource = (DataSource) initialContext.lookup("java:/comp/env/jdbc/redmine"); 
     System.out.println("Base de donnée Redmine Localisée"); 
     return datasource; 

    } catch (NamingException e) { 
     e.printStackTrace(); 
     return null; 
    } 

} 

/** 
* Défini Hibernate pour la transaction à la base de données. 
* 
* @return 
*/ 
@Bean(name="hibernateTransactionManagerOutil") 
public HibernateTransactionManager hibernateTransactionManagerOutil() { 
    System.out.println("initialisation du transaction manager pour l'outil !"); 
    return new HibernateTransactionManager(this.sessionFactoryOutil()); 
} 

@Bean(name="hibernateTransactionManagerRedmine") 
public HibernateTransactionManager hibernateTransactionManagerRedmine() { 
    System.out.println("initialisation du transaction manager pour Redmine !"); 
    return new HibernateTransactionManager(this.sessionFactoryRedmine()); 
} 
+0

何か(クエリ?あなたはそれを別のものとして扱っています。そして? – DN1

+0

私のリポジトリに言及するのを忘れて、私のポストを更新しました。問題が拡張するオブジェクトとしてそこにキャストされているクラスなぜキャスト例外があるべきですか?私はそれがマッピングから来ていると思っています。私はJavaがそのような振る舞いをしていると信じています。なぜなら、彼は着信データオブジェクトに対応するIssueオブジェクトを構築できないからです。 –

+0

JPA(使用しているものであれば、 "Session"はありません)は、 "SQL"を 'createQuery'に取り入れません。それはJPQLを取ります。そして、あなたが投稿するクエリ(結果句付き)があなたが呼んでいるものであれば、JPA仕様 – DN1

答えて

0

[OK]を私が見る、私は同じクエリで複数のオブジェクトを返すことができなかった、あなたが言ったように、実際には、JPAの問題ではありませんでした。私は3つのクエリ(私が思う汚い方法)のクエリを分割してそれを通過することができた、それは動作しますが、私はまだそれを行うクリーナーの方法を探しています

関連する問題