Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ java {
dependencies {
implementation 'org.hibernate:hibernate-core:5.5.6.Final'
runtimeOnly 'org.postgresql:postgresql:42.2.23.jre7'
implementation 'com.vladmihalcea:hibernate-types-52:2.12.1'
implementation 'org.slf4j:slf4j-api:1.7.32'

compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'

Expand Down
28 changes: 19 additions & 9 deletions src/main/java/com/dmdev/HibernateRunner.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.dmdev;

import com.dmdev.converter.BirthdayConverter;
import com.dmdev.entity.User;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import java.sql.SQLException;
import java.time.LocalDate;

public class HibernateRunner {

Expand All @@ -21,20 +22,29 @@ public static void main(String[] args) throws SQLException {
Configuration configuration = new Configuration();
// configuration.setPhysicalNamingStrategy(new CamelCaseToUnderscoresNamingStrategy());
// configuration.addAnnotatedClass(User.class);
configuration.addAttributeConverter(new BirthdayConverter());
configuration.registerTypeOverride(new JsonBinaryType());
configuration.configure();

try (SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession()) {
session.beginTransaction();

User user = User.builder()
.username("ivan@gmail.com")
.firstname("Ivan")
.lastname("Ivanov")
.birthDate(LocalDate.of(2000, 1, 19))
.age(20)
.build();
session.save(user);
// User user = User.builder()
// .username("ivan9@gmail.com")
// .firstname("Ivan")
// .lastname("Ivanov")
// .info("""
// {
// "name": "Ivan",
// "id": 25
// }
// """)
// .birthDate(new Birthday(LocalDate.of(2000, 1, 19)))
// .role(Role.ADMIN)
// .build();
// session.delete(user);
User user = session.get(User.class, "ivan@gmail.com");

session.getTransaction().commit();
}
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/dmdev/converter/BirthdayConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.dmdev.converter;

import com.dmdev.entity.Birthday;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.sql.Date;
import java.util.Optional;

@Converter(autoApply = true)
public class BirthdayConverter implements AttributeConverter<Birthday, Date> {

@Override
public Date convertToDatabaseColumn(Birthday attribute) {
return Optional.ofNullable(attribute)
.map(Birthday::birthDate)
.map(Date::valueOf)
.orElse(null);
}

@Override
public Birthday convertToEntityAttribute(Date dbData) {
return Optional.ofNullable(dbData)
.map(Date::toLocalDate)
.map(Birthday::new)
.orElse(null);
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/dmdev/entity/Birthday.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.dmdev.entity;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public record Birthday(LocalDate birthDate) {

public long getAge() {
return ChronoUnit.YEARS.between(birthDate, LocalDate.now());
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/dmdev/entity/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.dmdev.entity;

public enum Role {
ADMIN,
USER
}
18 changes: 15 additions & 3 deletions src/main/java/com/dmdev/entity/User.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
package com.dmdev.entity;

import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.LocalDate;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "users", schema = "public")
@TypeDef(name = "dmdev", typeClass = JsonBinaryType.class)
public class User {

@Id
private String username;
private String firstname;
private String lastname;

// @Convert(converter = BirthdayConverter.class)
@Column(name = "birth_date")
private LocalDate birthDate;
private Integer age;
private Birthday birthDate;

@Type(type = "dmdev")
private String info;

@Enumerated(EnumType.STRING)
private Role role;
}
68 changes: 68 additions & 0 deletions src/main/java/com/dmdev/type/JsonType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.dmdev.type;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JsonType implements UserType {

@Override
public int[] sqlTypes() {
return new int[0];
}

@Override
public Class returnedClass() {
return null;
}

@Override
public boolean equals(Object x, Object y) throws HibernateException {
return false;
}

@Override
public int hashCode(Object x) throws HibernateException {
return 0;
}

@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
return null;
}

@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {

}

@Override
public Object deepCopy(Object value) throws HibernateException {
return null;
}

@Override
public boolean isMutable() {
return false;
}

@Override
public Serializable disassemble(Object value) throws HibernateException {
return null;
}

@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return null;
}

@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return null;
}
}
87 changes: 87 additions & 0 deletions src/test/java/com/dmdev/HibernateRunnerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.dmdev;

import com.dmdev.entity.User;
import org.junit.jupiter.api.Test;

import javax.persistence.Column;
import javax.persistence.Table;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;

import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.joining;

class HibernateRunnerTest {

@Test
void checkGetReflectionApi() throws SQLException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
PreparedStatement preparedStatement = null;
ResultSet resultSet = preparedStatement.executeQuery();
resultSet.getString("username");
resultSet.getString("lastname");
resultSet.getString("lastname");

Class<User> clazz = User.class;

Constructor<User> constructor = clazz.getConstructor();
User user = constructor.newInstance();
Field usernameField = clazz.getDeclaredField("username");
usernameField.setAccessible(true);
usernameField.set(user, resultSet.getString("username"));
}

@Test
void checkReflectionApi() throws SQLException, IllegalAccessException {
User user = User.builder()
.build();

String sql = """
insert
into
%s
(%s)
values
(%s)
""";
String tableName = ofNullable(user.getClass().getAnnotation(Table.class))
.map(tableAnnotation -> tableAnnotation.schema() + "." + tableAnnotation.name())
.orElse(user.getClass().getName());

Field[] declaredFields = user.getClass().getDeclaredFields();

String columnNames = Arrays.stream(declaredFields)
.map(field -> ofNullable(field.getAnnotation(Column.class))
.map(Column::name)
.orElse(field.getName()))
.collect(joining(", "));

String columnValues = Arrays.stream(declaredFields)
.map(field -> "?")
.collect(joining(", "));

System.out.println(sql.formatted(tableName, columnNames, columnValues));

Connection connection = null;
PreparedStatement preparedStatement = connection.prepareStatement(sql.formatted(tableName, columnNames, columnValues));
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
preparedStatement.setObject(1, declaredField.get(user));
}
}










}