Warum bin ich immer JdbcSQLException (nicht-hex-Zeichen) mit meine H2-Datenbank / Spring-boot-Anwendung?
Also die kurze version, ich vermute, ich habe irgendeine Art von Zeichenkodierung Problem, oder der DB speichern/Rücksendung das Datum in einem format, Hibernate/Spring-jpa nicht mag aus irgendeinem Grund.
Aber ich bin jiggered wenn ich kann herausfinden, was falsch läuft!
Mit Hibernate 5 Gebrauch zu machen, J8 LocalDate Zeug in entity props.
Die Datenbank wird erstellt und die Daten eingefügt ok (sehen Sie in der log-Schnipsel unten bekomme ich einen date-Wert zurück).
Protokoll snippet:
2016-10-26 13:25:19.885 ERROR 1028 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException:
Could not read entity state from ResultSet : EntityKey[uk.co.deditech.entity.Person#2];
nested exception is org.hibernate.exception.GenericJDBCException: Could not read entity state from ResultSet :
EntityKey[uk.co.deditech.entity.Person#2]] with root cause org.h2.jdbc.JdbcSQLException: Hexadecimal string contains non-hex character: "2016-03-23" [90004-192]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.192.jar:1.4.192]
at org.h2.message.DbException.get(DbException.java:179) ~[h2-1.4.192.jar:1.4.192]
at org.h2.message.DbException.get(DbException.java:155) ~[h2-1.4.192.jar:1.4.192]
at org.h2.util.StringUtils.convertHexToBytes(StringUtils.java:986) ~[h2-1.4.192.jar:1.4.192]
at org.h2.value.Value.convertTo(Value.java:973) ~[h2-1.4.192.jar:1.4.192]
at org.h2.value.Value.getBytes(Value.java:422) ~[h2-1.4.192.jar:1.4.192]
at org.h2.jdbc.JdbcResultSet.getBytes(JdbcResultSet.java:1077) ~[h2-1.4.192.jar:1.4.192]
<snip>
Gradle:
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-freemarker")
compile group: 'com.h2database', name: 'h2', version:'1.4.192'
Person:
@Entity
@Table(name = "person")
public @Data class Person {
...
@Column(name = "last_grading_date", nullable = true)
private LocalDate lastGradingDate;
}
Spring-boot-auto-DB-Skript zum erstellen des snippets:
schema.sql
create table PERSON
(
id int not null,
last_grading_date date
)
data.sql
insert into person (id, last_grading_date)
values (1, '2015-02-20');
Eigenschaften (Problem trat sowohl vor und nach fügte ich die encoding-Eigenschaft unten):
spring.datasource.url=jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.datasource.sql-script-encoding=UTF-8
BEARBEITEN:
Nach etwas mehr Graben entdeckte ich auf "bestätigen" ist eine Einstellung für die Feder.jpa.hibernate.ddl-auto-Eigenschaft. Also versuchte ich das.
Bin ich jetzt immer folgende Fehlermeldung beim Start...
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [last_grading_date] in table [person]; found [date (Types#DATE)], but expecting [binary(255) (Types#VARBINARY)]
at org.hibernate.tool.schema.internal.SchemaValidatorImpl.validateColumnType(SchemaValidatorImpl.java:105) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
- Hinzufügen
org.hibernate:hibernate-java8
als eine Abhängigkeit, ohne dass er nicht weiß, wie Sie zu konvertieren von/zu Java8-Datum-Zeit-Objekte.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich es geschafft habe, durch hinzufügen dieser Abhängigkeit in meiner pom:
Ich weiß nicht, warum es nicht funktioniert out of the box, aber mit dieser Abhängigkeit um das Problem zu beheben.
Ich habe auch diese Eigenschaft unter Eigenschaften:
<hibernate.version>5.0.5.Final</hibernate.version>
Mein Beispielcode zum reproduzieren:
Daten.sql:
Anwendung.Eigenschaften
PersonRepository
Person
Applcation
Ergebnis:
2015-02-20
Hinzugefügt ein funktionierendes Beispiel auf GitHub. Die demo-build auf
Spring-boot
,Java 8
,Hibernate 5
,maven
undjava.time.LocalDate
.JPA 2.1 wurde veröffentlicht, bevor Sie Java 8 und die Datums-und Zeit-API einfach nicht vorhanden zu diesem Zeitpunkt. Daher die @Temporal-annotation kann nur angewendet werden auf Attribute vom Typ java.util.Date und java.util.Kalender.
Wenn Sie speichern möchten, eine
LocalDate
Attribut in einemDATE
Spalte oder eineLocalDateTime
imTIMESTAMP
Spalte, die Sie definieren müssen, die Zuordnung zujava.sql.Date
oderjava.sql.Timestamp
selbst.Attribut Konverter sind Teil der JPA 2.1-Spezifikation und kann daher verwendet werden, mit jedem JPA 2.1 Umsetzung, z.B. Hibernate oder EclipseLink. Ich verwendet Wildfly 8.2 mit Hibernate 4.3 für die folgenden Beispiele.
Konvertieren LocalDate
Wie Sie sehen können, die in den folgenden code-snippet, gibt es nicht viel Sie tun müssen, um ein Attribut zu erstellen Konverter für LocalDate.
Sie implementieren müssen, um die
AttributeConverter<LocalDate, Date>
- interface mit den beiden MethodenconvertToDatabaseColumn
undconvertToEntityAttribute
. Wie Sie sehen können auf den Methodennamen, eine von Ihnen ist bestimmt die Konvertierung aus dem Typ der Entität, Attribut (LocalDate
), um die Spalte in der Datenbank-Typ (Date
) und der andere die umgekehrte Konvertierung. Die Konvertierung selbst ist sehr einfach, weiljava.sql.Date
bietet bereits die Methoden, um die Konvertierung zu und von einemLocalDate
.Zusätzlich das Attribut converter muss sein, versehen mit den
@Converter
annotation. Durch die optionale autoApply=true-Eigenschaft, der Konverter angewendet werden, um alle Attribute des Typs LocalDate. Schauen Sie hier, wenn Sie möchten definieren Sie die Verwendung des Konverters für jedes Attribut einzeln.Die Umwandlung des Attributs ist für den Entwickler transparent und die
LocalDate
Attribut kann verwendet werden, wie jede andere Entität-Attribut. Sie können es verwenden, wie Sie einen query-parameter für Beispiel.Konvertieren LocalDateTime
Dem Attribut converter für
LocalDateTime
ist im Grunde das gleiche. Sie implementieren müssen, um dieAttributeConverter<LocalDateTime, Timestamp>
- Schnittstelle und dem Umrichter muss kommentiert werden mit dem @ - Konverter annotation. Ähnlich wie dieLocalDateConverter
der Konvertierung zwischenLocalDateTime
und einjava.sql.Timestamp
ist fertig mit der Konvertierung Methoden derTimestamp
.Beispiel Entity
In meinem Fall (Spring-Boot-1.5.10) alles was ich tun musste, war, fügen Sie den folgenden, um die pom.xml Eigenschaften Abschnitt
Sieht es aus wie Standard-version von Spring Boot nutzt Hibernate 5.0.12.Letzte
Du nicht angeben, den Typ der Spalte, für
last_grading_date
im Ruhezustand.Sie verwenden können:
Ändern
LocalDate
Klassejava.sql.Date
wenn das nicht funktioniert.private Date lastGradingDate;
mitDate
wirdjava.sql.Date
eher alsLocalDate