web-dev-qa-db-fra.com

La valeur '0000-00-00' ne peut pas être représentée par Java.sql.Date

Je travaille sur un projet qui doit extraire des données de la base de données et j'utilise Spring MVC pour créer un modèle à partir de la base de données afin de sélectionner des données.

Voici le problème avec ma page 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>

Comme vous pouvez le constater, j'essaie d'utiliser la bibliothèque de balises <form:select> from Spring.
Question:
mais quand il prépare mon modèle avec ce contrôleur:

@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";
        }

}

Cela me donne une erreur comme ceci:

WARN: org.springframework.web.servlet.PageNotFound - Aucun mappage trouvé pour une requête HTTP avec l'URI [/ controller /] dans DispatcherServlet avec nom 'appServlet' Hibernate: sélectionnez distinct creationda0_.DATE_ID en tant que DATE1_0_, creationda0_.CHILD_ADMISSION_DATE sous la forme CHILD2_0 _, creationda0_.CHILD_GO_SCHOOL_DATE sous la forme CHILD3_0 _, creationda0_.PARTICULAR_DATE comme PARTICULAR4_0_, creationda0_.VERSION sous la forme VERSION0_ de CREATION_DATE creationda0_ WARN: org.hibernate.util.JDBCExceptionReporter - Erreur SQL: 0, SQLState: S1009 ERREUR: org.hibernate.util.JDBCExceptionReporter - Valeur '0000-00-00' ne peut pas être représenté par Java.sql.Date 19 juin 2013 3:26:53 PM org.Apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service () pour servlet [appServlet] dans le contexte de chemin [/ contrôleur] a levé une exception [Le traitement de la demande a échoué; imbriqué exception est org.hibernate.exception.GenericJDBCException: impossible execute query] avec la cause première Java.sql.SQLException: valeur '0000-00-00' ne peut pas être représenté par Java.sql.Date

Si vous avez besoin de ma classe Entity, c'est ici que j'utilise Date de Java.util, mais je vais avec l'annotation @Temporal pour le convertir de SQL en unité Date telle que je la comprends:

@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;
        }


}

En supposant que le problème avec la conversion du type de données soit dû au fait que MVC utilise String, mais que le type réel est Date.

10
java_user

En MySql, '0000-00-00' est considéré comme une date valide, mais il ne peut pas être représenté sous la forme Java.sql.Date.

Vous pouvez utiliser une requête qui renvoie NULL si la date est '0000-00-00' ou la valeur réelle sinon:

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

ou vous pouvez ajouter à votre chaîne de connexion de source de données ceci:

zeroDateTimeBehavior=convertToNull

et les dates en tant que '0000-00-00' seront automatiquement converties en NULL.

32
fthiella

Ajoutez l'instruction suivante avec le protocole JDBC-mysql:

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

par exemple:

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

Ce n'est PAS toujours le problème NULL. Votre ensemble de données peut contenir des dates au format 05/23/2005 et l'exécution du chargeur entraînera l'insertion de 0000-00-00 dans votre colonne de type DATE. Les valeurs DATE, DATETIME ou TIMESTAMP non valides sont converties en valeur «zéro» du type approprié ('0000-00-00' ou '0000-00-00 00:00:00') (à partir du manuel MySQL).

Lors de la récupération à l'aide de SELECT, MySQL récupère la valeur au format YYYY-MM-DD' dans la plage de '1000-01-01' à '9999-12-31'. Alors tout votre 0000-00-00 commence à déconner.

Veillez donc non seulement à NULLs, mais également aux formats de date non pris en charge par MySQL.

Le mode RELAXED est pris en charge et n'importe quel caractère peut être utilisé comme séparateur comme / dans 05/23/2005 - vous pouvez également essayer.

3
Kingz

Je suppose que vous utilisez MySQL, vos colonnes de date ne sont pas obligatoires et peuvent donc contenir des valeurs NULL, mais MySQL fait des choses idiotes et renverra 0000-00-00 au lieu de NULL sauf si vous corrigez les paramètres du serveur MySQL.

2
Tassos Bassoukos

Pour moi, tout simplement ce qui suit a fonctionné. Grâce à @Yogesh H Bhosale et @fthiella réponds dans ce même fil de questions-réponses, j'ai trouvé la suggestion et l'ai améliorée.

Extrait de code:
Chaîne de connexion:

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

implémentation SQL-DB:

Et pour empêcher l’exception de pointeur nul lors de l’extraction de données (champ de date) à partir de l’ensemble de données renvoyé, j’ajoute le code suivant à l’instruction préparée.

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

Remarque:
Veuillez lire tous les commentaires dans la réponse pour une bonne compréhension.

2
Randika Vishman

Ajoutez zeroDateTimeBehavior=convertToNull à l'URL de connexion jdbc. 

String jdbcUrl="jdbc:mysql://localhost:3306/master_schema?zeroDateTimeBehavior=convertToNull"
1
Shanu Shine