I'm trying to insert objects of type Book into a database, and one of the columns is specified as date, but according to this exception:
Caused by: org.postgresql.util.PSQLException: ERROR: column "publish_date" is of type date but expression is of type bytea
Hint: You will need to rewrite or cast the expression.
Position: 94
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2412)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2125)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:297)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
... 11 more
is being put in as bytea. I'm not sure why this is the case, because in the database the column itself is of type date, and the column in my Book class is of type date. I can show the code below:
package examples.pubhub.model;
import java.time.LocalDate;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="books")
public class Book {
@Id
@Column(name="isbn_13")
public String isbn_13; // International Standard Book Number, unique
@Column(name="title")
private String title;
@Column(name="author")
private String author;
@Column(name="publish_date")
private LocalDate publish_date; // Date of publish to the website
@Column(name="price")
private double price;
@Column(name="content")
private byte[] content;
// Constructor used when no date is specified
public Book(String isbn, String title, String author, byte[] content, double price) {
super();
this.isbn_13 = isbn;
this.title = title;
this.author = author;
this.publish_date = LocalDate.now();
this.content = content;
this.price = price;
}
// Constructor used when a date is specified
public Book(String isbn, String title, String author, LocalDate publishDate, double price, byte[] content) {
super();
this.isbn_13 = isbn;
this.title = title;
this.author = author;
this.publish_date = publishDate;
this.content = content;
this.price = price;
}
// Default constructor
public Book() {
}
public String getIsbn_13() {
return isbn_13;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public LocalDate getPublish_date() {
return publish_date;
}
public void setPublish_date(LocalDate publishDate) {
this.publish_date = publishDate;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
public void setIsbn_13(String isbn) {
this.isbn_13 = isbn;
}
}
And this is the offline class I'm testing:
package examples.pubhub.utilities;
import java.time.LocalDate;
import examples.pubhub.dao.BookDAO;
import examples.pubhub.dao.BooktagDAO;
import examples.pubhub.model.Book;
import examples.pubhub.model.Booktag;
public class PublishBookTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
String isbn = "1234123412341";
String title = "Title";
String author = "Haisam";
String book_tag = "Science Fiction";
BookDAO database = DAOUtilities.getBookDAO();
Book tempBook = database.getBookByISBN(isbn);
BooktagDAO tagdao = DAOUtilities.getBooktagDAO();
Booktag tempBooktag = tagdao.getBookTagByISBN(isbn);
if (tempBook != null && tempBooktag != null) {
// ASSERT: book with isbn already exists
System.out.println("ISBN already exists.");
} else {
Book book = new Book();
Booktag booktag = new Booktag();
book.setIsbn_13(isbn);
book.setTitle(title);
book.setAuthor(author);
book.setPrice(124);
book.setPublish_date(LocalDate.now());
book.setContent(null);
booktag.setBook_tag(book_tag);
booktag.setBook_isbn(isbn);
booktag.setBook_title(title);
boolean isSuccess_booktag = tagdao.addTag(booktag);
boolean isSuccess_book = database.addBook(book);
if (isSuccess_book && isSuccess_booktag) {
System.out.println("Added.");
} else {
System.out.println("Not added.");
}
}
}
}
If anyone knows how to convert from bytea to date, or what the crux of this problem may be, I will be forever grateful. Thank you for your time.
TLDR: The transaction is not committing because of incompatible typing between LocalDate publish_date and the actual column publish_date in the database, which is of type date. Not sure why.
Create a
LocalDateToWhateverDBTypeConverter
. Here is how.Edit:
There are two options to define the usage of a Converter. The first one is to set
autoapply=true
at the@Converter
annotation of theConverter
class. In this case the JPA provider will use thisConverter
to convert all entity attributes of the given type. Ifautoapply
is set tofalse
, you need to add thejavax.persistence.Convert
annotation to all attributes that shall be converted and specify theConverter
class. The following code snippet shows an example for this approach: