Good afternoon, please tell me, is it possible to get the name of the columns of the unloading of the SQL query in Hibernate? The crux of the matter, there is a web service report, there is XML where the requests are stored. There is a conclusion on JSP

<c:if test="${!empty reportList}"> <table> <!-- <tr> <th><spring:message code="issuenum" /></th> <th><spring:message code="PROJECT" /></th> <th><spring:message code="SUMMARY" /></th> <th><spring:message code="CREATED" /></th> </tr>--> <c:forEach items="${reportList}" var="report"> <tr> <c:forEach var="i" begin = "0" end = "${lenght}"> <td>${report[i]}</td> </c:forEach> </tr> </c:forEach> </table> 

But I also need to do to get dynamic columns, it is necessary for universality, so that you can add reports from the page, then map with XML with queries to avoid recompiling the warlord. Stored procedures will be written to XML as a result in order to also avoid creating table entities.

Is it possible to somehow be realized or not, you still have to do something with warnik when adding a reference + query to XML?

Maybe someone did that? Or suggest any other solution. But the essence is that the user can add the necessary report to himself.

UPDATE:

Implementation through procedures is done in order to avoid JOINs, etc., since hibernate is complicated with this, even with the same concate, in order to do this, you need to essentially add an annotation

Request to the database

 SELECT CONCAT(l.jiraissue.project_def.pkey, l.jiraissue.fullName2) as clmName, l.cwd_user.display_name, l.worklogbody, l.startdate, l.timeworked/3600 FROM worklog as l 

How do I get the names of the fields, exactly those that are in select and in the same order, given that I used the join annotation with the table cwd_user and jiraissue?

Class entity

 @Entity @Table(name = "worklog") public class worklog implements Serializable { private static final long serialVersionUID = -3754944057116773016L; @ManyToOne @JoinColumn(name = "issueid", insertable = false, updatable = false) private jiraissue jiraissue; public jiraissue getJiraissue() { return jiraissue; } public void setJiraissue(jiraissue jiraissue) { this.jiraissue = jiraissue; } @ManyToOne @JoinColumn(name = "AUTHOR", insertable = false, updatable = false) private cwd_user cwd_user; public cwd_user getCwd_user() { return cwd_user; } public void setCwd_user(cwd_user cwd_user) { this.cwd_user = cwd_user; } @Id @Column(name = "ID") private int id; @Column(name = "issueid") private int issueid; @Column(name = "AUTHOR") private String author; @Column(name = "worklogbody") private String worklogbody; @Column(name = "STARTDATE") private Date startdate; @Column(name = "timeworked") private int timeworked; геттеры и сеттеры 

plus 2 more classes

The controller from which I transfer to JSP

 @Controller public class ReportingServicesController { @Autowired private ReportingServicesService reportingServicesService; @RequestMapping(value = "/", method = RequestMethod.GET) public String home() { return "welcome"; } private List<? extends Object> list = null; private String nameRequest = null; private String[] columns = null; // Получения результата отчета @RequestMapping(value = "/report", method = RequestMethod.GET) public String reportList(@RequestParam(value = "user", required = false, defaultValue = "") String user, @RequestParam(value = "request", required = false) String request, @RequestParam(value = "start", required = false, defaultValue = "") String start, @RequestParam(value = "end", required = false, defaultValue = "") String end, Map<String, Object> map) { // временная проверка if (user.equals("")) { list = reportingServicesService.listReport(request); } else { list = reportingServicesService.listReport(user, request, start, end); columns = reportingServicesService.getColumnNames(); } nameRequest = request; // map.put("jiraissue", new jiraissue()); map.put("reportList", list); map.put("lenght", reportingServicesService.getLenghtArrayList(list)); map.put("columns", columns); return "reports"; } 

DAOImpl Method for executing a query, the query itself is taken from XML

 @SuppressWarnings("unchecked") public List<? extends Object> listReport(String user, String nameRequest, String start, String end) { return sessionFactory.getCurrentSession().createQuery(ParserQueryXML.getQueryFromXML(nameRequest)) .setString("user", user).setString("start", start).setString("end", end).list(); } 

JSP itself

 <c:if test="${!empty reportList}"> <table> <tr> <c:forEach var="i" begin = "0" end = "${lenght}"> <th><spring:message code="${columns[i]}" /></th> </c:forEach> </tr> <c:forEach items="${reportList}" var="report"> <tr> <td><a href="https://jira.ru/browse/${report[0]}" target="_blank">${report[0]}</a></td> <c:forEach var="i" begin = "1" end = "${lenght}"> <td>${report[i]}</td> </c:forEach> </tr> </c:forEach> </table> 

I could do everything easier, specify in the manual fields, but the task is not to campile and not to climb into the code at all. I kind of did everything, but only with the fields left (((

In the future, all the procedures will translate, so as not to create classes of the entity

    2 answers 2

    Getting entity fields is simple:

     String[] columnNames = getSessionFactory() .getClassMetadata(Report.class) .getPropertyNames(); 

    It is impossible to get the fields from the List<Object[]> , which returns the Query.list () method when enumerating the fields in the query explicitly without explicitly specifying their mapping to some class, since there is simply no place to store this information in the list of arrays of objects.

    It remains to write some helper, which will extract from the xml not only the request, but also the list of field names. Or describe for each DTO request, return it instead of an array and call its method in the template, which returns a list of the names of its fields:

     public class SomeReportDTO { private final String clmName; private final String displayName; private final String worklogBody; private final Long startDate; private final Long timeWorked; public SomeReportDTO(String clmName, String displayName, String worklogBody, Long startDate, Long timeWorked) { this.clmName = clmName; ... } public String[] getFieldNames() { return new String[] { "Какое-то имя"; "Дисплейное имя"; ... }; } } 
    • Yes, I saw this method, but what if I have join'y have SELECT CONCAT (l.jiraissue.project_def.pkey, l.jiraissue.fullName2), l.cwd_user.display_name, l.worklogbody, l.startdate, l .timeworked / 3600 FROM worklog as l WHERE. It is necessary for me to deduce such columns, but not from one class of entity. - Vladislav
    • that is, I mean that he brought me all the columns [author, cwd_user, issueid, jiraissue, startdate, timeworked, worklogbody], as a result, when I built the report, the name and the content did not match. And I just need him to display the columns that I requested. So you can do? those. so that he brought me [jiranum, cwd_user, workbody, startdate, timework] in that particular order. - Vladislav
    • Your query with joines that returns you a list of arrays of objects or a list of DTO? - Sergey Gornostaev
    • I didn’t understand the question a bit, it returns data from the database to me, according to the fields I specified in select, but a request for field names returns an array of all the names from the worklog class, and also sorts by name. - Vladislav
    • Edit your question, add a sample code from the database. - Sergey Gornostaev

    Class entity

     @Entity @Table(name = "worklog") public class worklog implements Serializable { private static final long serialVersionUID = -3754944057116773016L; @ManyToOne @JoinColumn(name = "issueid", insertable = false, updatable = false) private jiraissue jiraissue; public jiraissue getJiraissue() { return jiraissue; } public void setJiraissue(jiraissue jiraissue) { this.jiraissue = jiraissue; } @ManyToOne @JoinColumn(name = "AUTHOR", insertable = false, updatable = false) private cwd_user cwd_user; public cwd_user getCwd_user() { return cwd_user; } public void setCwd_user(cwd_user cwd_user) { this.cwd_user = cwd_user; } @Id @Column(name = "ID") private int id; @Column(name = "issueid") private int issueid; @Column(name = "AUTHOR") private String author; @Column(name = "worklogbody") private String worklogbody; @Column(name = "STARTDATE") private Date startdate; @Column(name = "timeworked") private int timeworked; геттеры и сеттеры 

    plus 2 more classes

    The controller from which I transfer to JSP

     @Controller public class ReportingServicesController { @Autowired private ReportingServicesService reportingServicesService; @RequestMapping(value = "/", method = RequestMethod.GET) public String home() { return "welcome"; } private List<? extends Object> list = null; private String nameRequest = null; private String[] columns = null; // Получения результата отчета @RequestMapping(value = "/report", method = RequestMethod.GET) public String reportList(@RequestParam(value = "user", required = false, defaultValue = "") String user, @RequestParam(value = "request", required = false) String request, @RequestParam(value = "start", required = false, defaultValue = "") String start, @RequestParam(value = "end", required = false, defaultValue = "") String end, Map<String, Object> map) { // временная проверка if (user.equals("")) { list = reportingServicesService.listReport(request); } else { list = reportingServicesService.listReport(user, request, start, end); columns = reportingServicesService.getColumnNames(); } nameRequest = request; // map.put("jiraissue", new jiraissue()); map.put("reportList", list); map.put("lenght", reportingServicesService.getLenghtArrayList(list)); map.put("columns", columns); return "reports"; } 

    DAOImpl Method for executing a query, the query itself is taken from XML

     @SuppressWarnings("unchecked") public List<? extends Object> listReport(String user, String nameRequest, String start, String end) { return sessionFactory.getCurrentSession().createQuery(ParserQueryXML.getQueryFromXML(nameRequest)) .setString("user", user).setString("start", start).setString("end", end).list(); } 

    JSP itself

     <c:if test="${!empty reportList}"> <table> <tr> <c:forEach var="i" begin = "0" end = "${lenght}"> <th><spring:message code="${columns[i]}" /></th> </c:forEach> </tr> <c:forEach items="${reportList}" var="report"> <tr> <td><a href="https://jira.ru/browse/${report[0]}" target="_blank">${report[0]}</a></td> <c:forEach var="i" begin = "1" end = "${lenght}"> <td>${report[i]}</td> </c:forEach> </tr> </c:forEach> </table> 

    I could do everything easier, specify in the manual fields, but the task is not to campile and not to climb into the code at all. I kind of did everything, but only with the fields left (((

    In the future, all the procedures will translate, so as not to create classes of the entity