-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());
}
何か(クエリ?あなたはそれを別のものとして扱っています。そして? – DN1
私のリポジトリに言及するのを忘れて、私のポストを更新しました。問題が拡張するオブジェクトとしてそこにキャストされているクラスなぜキャスト例外があるべきですか?私はそれがマッピングから来ていると思っています。私はJavaがそのような振る舞いをしていると信じています。なぜなら、彼は着信データオブジェクトに対応するIssueオブジェクトを構築できないからです。 –
JPA(使用しているものであれば、 "Session"はありません)は、 "SQL"を 'createQuery'に取り入れません。それはJPQLを取ります。そして、あなたが投稿するクエリ(結果句付き)があなたが呼んでいるものであれば、JPA仕様 – DN1