类Cast Exception - Hibernate映射+ Spring MVC

时间:2017-11-20 09:10:51

标签: hibernate class jpa exception casting

早上好, 我正在开发一个跟踪业务指标的应用程序。数据库不常见,导致复杂的查询(在我的级别)和复杂的映射。能否请你帮我看看下面的堆栈跟踪:

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());
}

1 个答案:

答案 0 :(得分:0)

好的,我看到,我无法在同一个查询中返回多个对象,实际上并不像你说的那样是JPA问题。我设法通过它将查询划分为3个查询(我认为是肮脏的方式),它可以工作,但我仍然会寻找一种更清晰的方式来实现这一目标