Значение "0000-00-00" не может быть представлено как java.sql.Date

Я работаю над некоторым проектом, который должен извлекать данные из БД, и я использую Spring MVC для построения модели из БД для выбора данных.

Вот проблема с моей страницей JSP:

<form action="result" method="get" >
<table>
<thead>
<tr>
<th>Date to select:</th>
<th>Name to select:</th>
<th>Type to select:</th>
</tr>
</thead>

<tbody>
<tr>
<td><form:select  path="listOfDates">
<form:option value="NONE"> --SELECT--</form:option>
<form:options items="${listOfDates}"></form:options>
</form:select>
</td>  
<td><form:select  path="listOfInstitutionsNames">
<form:option value="NONE"> --SELECT--</form:option>
<form:options items="${listOfInstitutionsNames}"></form:options>
</form:select>
</td>
<td>
<form:select  path="listOfInstitutionsTypes">
<form:option value="NONE"> --SELECT--</form:option>
<form:options items="${listOfInstitutionsTypes}"></form:options>
</form:select>
</td>
</tr>
</tbody>

<tfoot>
<tr>
<td><input type="submit" value="Извлечь"/></td>
</tr>
</tfoot>

</table>
</form>

Как вы можете видеть, я пытаюсь использовать библиотеку тегов <form:select> из Spring.
Вопрос:
но когда он готовит мою модель с помощью этого контроллера:

@Controller
public class HomeController{ 

    @Autowired
    private ControllerSupportClass controllerSupportClass; 


        @RequestMapping(value="/search", method=RequestMethod.GET)
        public String search(Model model) {
            List<Date> listOfDates = controllerSupportClass.findAllDatesForm();
            List<String> listOfInstitutionsNames = controllerSupportClass.findAllInstitutionsForm();
            List<String> listOfInstitutionsTypes = controllerSupportClass.findAllTypesForm();
            model.addAttribute("listOfInstitutionsTypes", listOfInstitutionsTypes);
            model.addAttribute("listOfInstitutionsNames", listOfInstitutionsNames);
            model.addAttribute("listOfDates", listOfDates);
            return "search";    
        }


        @RequestMapping(value ="/result", method=RequestMethod.GET)
        public String SecondActionPage(@RequestParam String particularDate, 
                                       @RequestParam String nameOfInstitution, 
                                       @RequestParam String typeName,
                                       Model model) throws Exception {


                if(particularDate !="" && nameOfInstitution.trim() !="" && typeName.trim()=="") {                   
                    controllerSupportClass.findWithDateAndName(nameOfInstitution, particularDate, model);                   
                } else if(particularDate.trim() !="" && nameOfInstitution.trim() =="" && typeName.trim() !="") {                    
                    controllerSupportClass.findWithAddedDateAndType(typeName, particularDate, model);                   
                } else if(particularDate.trim() !="" && nameOfInstitution.trim() =="" && typeName.trim() ==""){         
                    controllerSupportClass.findWithAddedDate(particularDate, model);    
                } else if(particularDate.trim() !="" && nameOfInstitution.trim() !="" && typeName.trim() !="") {
                    throw new Exception("Search by choose all parameters is not exceptable");   
                } else {    
                    throw new Exception("You didn't put any search parameters");    
                }           
            return "search";
        }

}

Это приводит к ошибке:

WARN: org.springframework.web.servlet.PageNotFound - картирование не найдено для HTTP-запроса с URI [/controller/] в DispatcherServlet с name 'appServlet' Hibernate: выберите отдельное созданиеda0_.DATE_ID как DATE1_0_, createda0_.CHILD_ADMISSION_DATE как CHILD2_0_, createda0_.CHILD_GO_SCHOOL_DATE как CHILD3_0_, createda0_.PARTICULAR_DATE как PARTICULAR4_0_, созданиеda0_.VERSION как VERSION0_ from CREATION_DATE creationda0_ WARN: org.hibernate.util.JDBCExceptionReporter - Ошибка SQL: 0, SQLState: S1009 ОШИБКА: org.hibernate.util.JDBCExceptionReporter - значение '0000-00-00' не может быть представлен как java.sql.Date 19 июня 2013 г. 3:26:53 PM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() для сервлета [appServlet] в контексте с path [/controller] выбрал исключение [Ошибка обработки запроса; вложенными Исключением является org.hibernate.exception.GenericJDBCException: не удалось выполнить запрос] с корневой причиной java.sql.SQLException: Value '0000-00-00' не может быть представлен как java.sql.Date

Если вам нужен мой класс Entity, здесь я использую Date от java.util, но я иду с аннотацией @Temporal, чтобы преобразовать его из SQL в unit Date, как я понимаю:

@Entity
@Table(name="CREATION_DATE")
public class CreationDate implements Serializable {


    private int dateId;

        @Id
        @GeneratedValue(strategy=IDENTITY)
        @Column(name="DATE_ID")
        public int getDateId() {
            return dateId;
        }

        public void setDateId(int dateId) {
            this.dateId = dateId;
        }


    private int version;

        @Version
        @Column(name="VERSION")
        public int getVersion() {
            return version;
        }

        public void setVersion(int version) {
            this.version = version;
        }


    private Date particularDate;

        @Temporal(TemporalType.DATE)
        @DateTimeFormat(pattern="yyyy-MM-dd")
        @Column(name="PARTICULAR_DATE")
        public Date getParticularDate() {
            return particularDate;
        }

        public void setParticularDate(Date particularDate) {
            this.particularDate = particularDate;
        }


    private Date childGoSchoolDate;

        @Temporal(TemporalType.DATE)
        @DateTimeFormat(pattern="yyyy-MM-dd")
        @Column(name="CHILD_GO_SCHOOL_DATE")
        public Date getChildGoSchoolDate() {
            return childGoSchoolDate;
        }

        public void setChildGoSchoolDate(Date childGoSchoolDate) {
            this.childGoSchoolDate = childGoSchoolDate;
        }


    private Date childAdmissionDate;

        @Temporal(TemporalType.DATE)
        @DateTimeFormat(pattern="yyyy-MM-dd")
        @Column(name="CHILD_ADMISSION_DATE")
        public Date getChildAdmissionDate() {
            return childAdmissionDate;
        }

        public void setChildAdmissionDate(Date childAdmissionDate) {
            this.childAdmissionDate = childAdmissionDate;
        }


}

Предполагая, что проблема с преобразованием типа данных связана с тем, что MVC использует String, но фактический тип Date.

Ответ 1

В MySql '0000-00-00' считается допустимой датой, но он не может быть представлен как java.sql.Date.

Вы можете использовать запрос, который возвращает NULL в случае, если дата даты '0000-00-00', или фактическое значение в противном случае:

SELECT
  CASE WHEN `date`!='0000-00-00' THEN `date` END new_date
FROM
  yourtable

или вы можете добавить к своей строке подключения к источнику данных следующее:

zeroDateTimeBehavior=convertToNull

и даты как '0000-00-00' будут автоматически преобразованы в NULL.

Ответ 2

Добавьте следующий оператор в протокол JDBC-mysql:

"?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8"

для примера:

jdbc:mysql://localhost/infra?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8

Ответ 3

Это не всегда проблема NULL. Ваш набор данных может содержать даты в формате 05/23/2005, а запуск загрузчика приведет к его вставке 0000-00-00 в столбец типа DATE. Недопустимые значения DATE, DATETIME или TIMESTAMP преобразуются в нулевое значение соответствующего типа ('0000-00-00' или '0000-00-00 00:00:00') (из Руководство по MySQL)

При извлечении с помощью SELECT MySQL извлекает значение в формате YYYY-MM-DD' в диапазоне от '1000-01-01' до '9999-12-31'. Таким образом, все ваши 0000-00-00 начинают прикручиваться.

Поэтому следите не только за NULLs, но и за форматы даты, не поддерживаемые MySQL.

Поддерживается режим RELAXED, где любой символ может использоваться как разделители типа / в 05/23/2005 - вы также можете попробовать это.

Ответ 4

Моя дикая догадка заключается в том, что вы используете MySQL, ваши столбцы даты не являются обязательными и, следовательно, могут содержать NULL, но MySQL делает идиотские вещи и вернет 0000-00-00 вместо NULL, если вы не исправите настройки сервера MySQL.

Ответ 5

Для меня просто работало. Благодаря ответу @Yogesh H Bhosale и @fthiella в этом же потоке Q-A я нашел подсказку и улучшил ее.

Фрагмент кода:
Строка подключения:

private static String CONNECTION_STR = "jdbc:mysql://localhost:3306/water_billing?zeroDateTimeBehavior=convertToNull";

Реализация SQL-DB:

И чтобы предотвратить исключение Null Pointer во время вывода данных (поле даты) из возвращаемого набора данных, я добавляю следующий код в подготовленный отчет.

Connection conn = DriverManager.getConnection(CONNECTION_STR,USERNAME,PASSWORD);   //   Get connection to the DB to execute the query. You will have to handle exceptions here too..
String SQL = "SELECT dateField FROM my_payments_tbl";
ResultSet rs = conn.createStatement().executeQuery(SQL);
LocalDate prvPaymentDate = null;

while (rs.next())
{
     // Following is the next Important line.
     prvPaymentDate = (rs.getDate(1) != null) ? rs.getDate(1).toLocalDate() : null;    // Checks if it comes as a Null or a Real java.sql.Date object.

     // Depending on the value of the column in the current row, prvPaymentDate could be null.
     // Specially as we instructed via the Connection String, 0000-00-00 00:00:00 will come now as SQL NULL objects.
     // So we filter out them in the above line and assigns null, instead of LocalDate objects.
     if (prvPaymentDate != null)
        System.out.println("date "+prvPaymentDate.toString());
}

Примечание:
Пожалуйста, прочитайте все комментарии в ответе для хорошего понимания.