JPA Fundamentals & Hibernate - 2) @Id generation
In this post, we are going to find out “what are the options to provide automatic Id generation instead of setting manually”. We will look …
In this post, we are going to learn @Enumarated
and @Temporal
annotations, how to store enums as ordinal and string and when to store enum types to the database. Also we are going to learn how to work with date types and when we need to use @Temporal annotation
If you only need to see the code, here is the github link
Create table called price, which has a currency column. Enum values will be used for currency column.
CREATE TABLE price
(
id SERIAL PRIMARY KEY,
amount NUMERIC,
currency INT
);
Pretty-simple :
public enum Currency {
DOLLAR, EURO, TL
}
@Entity
@Table(name = "price")
public class Price {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private double amount;
@Enumerated(EnumType.ORDINAL) // ORDINAL is the default value
private Currency currency;
}
When you use EnumType.ORDINAL:
Currency.DOLLAR
will be stored as 0 (zero)Currency.EURO
: will be stored as 1Currency.TL
: will be stored as 2.Let’s run the main method:
public class Main {
public static final String PERSISTENCE_UNIT = "postgresqlPersistenceUnit";
public static void main(String[] args) {
// ...
Price price = new Price();
price.setAmount(10.34);
price.setCurrency(Currency.TL);
Price anotherPrice = new Price();
anotherPrice.setAmount(5.34);
anotherPrice.setCurrency(Currency.EURO);
try {
entityManager.getTransaction().begin();
entityManager.persist(price);
entityManager.persist(anotherPrice);
entityManager.getTransaction().commit();
}catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
} finally {
entityManager.close();
}
}
}
After that look at the table in the database:
select * from price;
-- 2 = TL, 1 = DOLLAR
id | amount | currency
----+--------+----------
1 | 10.34 | 2
2 | 5.34 | 1
(2 rows)
DROP TABLE price ;
CREATE TABLE price
(
id SERIAL PRIMARY KEY,
amount NUMERIC,
currency VARCHAR(100)
);
@Enumarated
annotation:@Enumerated(EnumType.STRING)
private Currency currency;
select * from price;
id | amount | currency
----+--------+----------
1 | 10.34 | TL
2 | 5.34 | EURO
(2 rows)
Whenever it is possible, please use the EnumType.STRING
. Let’s say after period of time we need to add another currency :
public enum Currency {
DOLLAR, EURO, TL, GBP
}
If you add GBP at the end, you will not face any problem (when using ORDINAL). However if you place GBP at the beginning, index 0 will become GBP and index 3 will be become DOLLAR and it leads to the corruption in your database. Because most probably you will have records with index 0 which indicate DOLLAR.
The PostgreSQL JDBC driver implements native support for the Java 8 Date and Time API (JSR-310) using JDBC 4.2.
PostgreSQL | Java SE 8 |
---|---|
DATE | LocalDate |
TIME [ WITHOUT TIMEZONE ] | LocalTime |
TIMESTAMP [ WITHOUT TIMEZONE ] | LocalDateTime |
TIMESTAMP WITH TIMEZONE | OffsetDateTime |
Let’s learn how to use Date types in the JPA.
JPA 2.2 supports
LocalDate
, so no converter is needed.Hibernate also supports it as of 5.3 version.
You don’t need to convert any of the following date:
java.time.LocalDate java.time.LocalTime java.time.LocalDateTime java.time.OffsetTime java.time.OffsetDateTime
First create a table called simple_date
:
CREATE table simple_date
(
id SERIAL PRIMARY KEY,
only_date DATE,
only_time TIME,
date_with_time TIMESTAMP
);
Then create an entity class for the table:
@Entity
@Table(name = "simple_date")
public class SimpleDate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "only_date")
private LocalDate onlyDate;
@Column(name = "only_time")
private LocalTime localTime;
@Column(name = "date_with_time")
private LocalDateTime dateWithTime;
}
Run the main method:
public class Main {
public static void main(String[] args) {
SimpleDate date = new SimpleDate();
date.setOnlyDate(LocalDate.now());
date.setLocalTime(LocalTime.now());
date.setDateWithTime(LocalDateTime.now());
SimpleDate anotherDate = new SimpleDate();
anotherDate.setOnlyDate(LocalDate.now());
anotherDate.setLocalTime(LocalTime.now());
anotherDate.setDateWithTime(LocalDateTime.now());
try {
entityManager.getTransaction().begin();
entityManager.persist(date);
entityManager.persist(anotherDate);
entityManager.getTransaction().commit();
}catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
} finally {
entityManager.close();
}
}
}
Look at the table:
select * from simple_date;
id | only_date | only_time | date_with_time
----+------------+-----------+----------------------------
1 | 2021-08-01 | 17:46:04 | 2021-08-01 17:46:04.219018
2 | 2021-08-01 | 17:46:04 | 2021-08-01 17:46:04.219038
To work with java Date or Calendar
package, you need to use @Temporal
annotation. Because Java doesn’t really know how to directly relate to SQL types.
java.util Date and Calendar
are legacy packages. It is better to usejava.time.package.
Here is the simple example:
@Entity
@Table(name = "simple_date")
public class SimpleDate {
// ...
@Column(name = "date")
@Temporal(TemporalType.DATE)
private Date date;
@Temporal(value=TemporalType.TIMESTAMP)
@Column(name="timestampm")
private Date updatedTime;
// ...
}
Last but not least, wait for the next post …
In this post, we are going to find out “what are the options to provide automatic Id generation instead of setting manually”. We will look …
In this series, we are going to learn the JPA fundamentals and we are going to use one of its implementation Hibernate. Before diving into the series, …