Skip to content

Commit

Permalink
Add YearMonthTimestampType #127
Browse files Browse the repository at this point in the history
In some legacy schemas it might be required to map a YearMonth to a
Timestamp value, rather than the Date value that we currently support.

This may for example be chosen for easy range comparisions to other
timestamp values without any casting being required.

This change adds such a YearMonthTimestampType. While I think
YearMonthDateType will generally be the preferred type, this at least
should smoothen the transition from a YearMonth modelled as a timestamp
to a YearMonth value.
  • Loading branch information
jwgmeligmeyling authored and vladmihalcea committed Sep 14, 2019
1 parent 5b9a730 commit 956747d
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 0 deletions.
2 changes: 2 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Version 2.7.0 - IN PROGRESS

Add support for JSON column values for Oracle #131

Add YearMonthTimestampType #127

Ability to use PostgreSQLEnumType and EnumArrayType with TypedParameterValue #125

Version 2.6.1 - August 29, 2019
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.vladmihalcea.hibernate.type.basic;

import com.vladmihalcea.hibernate.type.AbstractHibernateType;
import com.vladmihalcea.hibernate.type.basic.internal.YearMonthTypeDescriptor;
import com.vladmihalcea.hibernate.type.util.Configuration;
import org.hibernate.type.descriptor.sql.DateTypeDescriptor;
import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;

import java.time.YearMonth;

/**
* Maps a Java {@link YearMonth} object to a {@code TIMESTAMP} column type.
* <p>
*
* @author Vlad Mihalcea
*/
public class YearMonthTimestampType
extends AbstractHibernateType<YearMonth> {

public static final YearMonthTimestampType INSTANCE = new YearMonthTimestampType();

public YearMonthTimestampType() {
super(
TimestampTypeDescriptor.INSTANCE,
YearMonthTypeDescriptor.INSTANCE
);
}

public YearMonthTimestampType(Configuration configuration) {
super(
TimestampTypeDescriptor.INSTANCE,
YearMonthTypeDescriptor.INSTANCE,
configuration
);
}

public String getName() {
return "yearmonth-timestamp";
}

@Override
protected boolean registerUnderJavaType() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;

import java.sql.Timestamp;
import java.time.Instant;
import java.time.YearMonth;
import java.time.ZoneId;
Expand Down Expand Up @@ -49,6 +50,9 @@ public <X> X unwrap(YearMonth value, Class<X> type, WrapperOptions options) {
Integer numericValue = (value.getYear() * 100) + value.getMonth().getValue();
return (X) (numericValue);
}
if (Timestamp.class.isAssignableFrom(type)) {
return (X) java.sql.Timestamp.valueOf(value.atDay(1).atStartOfDay());
}
if (Date.class.isAssignableFrom(type)) {
return (X) java.sql.Date.valueOf(value.atDay(1));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.vladmihalcea.hibernate.type.basic;

import com.vladmihalcea.hibernate.type.util.AbstractPostgreSQLIntegrationTest;
import org.hibernate.Session;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.TypeDef;
import org.junit.Test;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.YearMonth;

import static org.junit.Assert.assertEquals;

/**
* @author Vlad Mihalcea
*/
public class PostgreSQLYearMonthTimestampTest extends AbstractPostgreSQLIntegrationTest {

@Override
protected Class<?>[] entities() {
return new Class<?>[]{
Book.class
};
}

@Test
public void test() {
doInJPA(entityManager -> {
Book book = new Book();
book.setIsbn("978-9730228236");
book.setTitle("High-Performance Java Persistence");
book.setPublishedOn(YearMonth.of(2016, 10));

entityManager.persist(book);
});

doInJPA(entityManager -> {
Book book = entityManager
.unwrap(Session.class)
.bySimpleNaturalId(Book.class)
.load("978-9730228236");

assertEquals(YearMonth.of(2016, 10), book.getPublishedOn());
});

doInJPA(entityManager -> {
Book book = entityManager
.createQuery(
"select b " +
"from Book b " +
"where " +
" b.title = :title and " +
" b.publishedOn = :publishedOn", Book.class)
.setParameter("title", "High-Performance Java Persistence")
.setParameter("publishedOn", YearMonth.of(2016, 10))
.getSingleResult();

assertEquals("978-9730228236", book.getIsbn());
});
}


@Entity(name = "Book")
@Table(name = "book")
@TypeDef(typeClass = YearMonthTimestampType.class, defaultForType = YearMonth.class)
public static class Book {

@Id
@GeneratedValue
private Long id;

@NaturalId
private String isbn;

private String title;

@Column(name = "published_on", columnDefinition = "date")
private YearMonth publishedOn;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getIsbn() {
return isbn;
}

public void setIsbn(String isbn) {
this.isbn = isbn;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public YearMonth getPublishedOn() {
return publishedOn;
}

public void setPublishedOn(YearMonth publishedOn) {
this.publishedOn = publishedOn;
}
}
}

0 comments on commit 956747d

Please sign in to comment.