Добавлен Hybernate и реализован прототип БД

This commit is contained in:
RoyceDa
2026-02-02 03:20:12 +02:00
parent fb41458b18
commit d1be8e7014
8 changed files with 452 additions and 7 deletions

View File

@@ -2,15 +2,27 @@ version: '3.8'
services: services:
db: db:
image: postgres:latest image: postgres:16-alpine
environment: environment:
POSTGRES_DB: your_database POSTGRES_DB: rosetta_db
POSTGRES_USER: your_user POSTGRES_USER: rosetta_user
POSTGRES_PASSWORD: your_password POSTGRES_PASSWORD: rosetta_password
ports: ports:
- "5432:5432" - "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U rosetta_user"]
interval: 10s
timeout: 5s
retries: 5
adminer: adminer:
image: adminer image: adminer
ports: ports:
- "8080:8080" - "8080:8080"
depends_on:
- db
volumes:
postgres_data:

22
pom.xml
View File

@@ -16,13 +16,31 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.java-websocket</groupId> <groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId> <artifactId>Java-WebSocket</artifactId>
<version>1.6.0</version> <version>1.6.0</version>
</dependency> </dependency>
<!-- Hibernate ORM -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.4.0.Final</version>
</dependency>
<!-- PostgreSQL JDBC Driver -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.1</version>
</dependency>
<!-- Jakarta Persistence API -->
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -0,0 +1,29 @@
package com.rosetta.im.database;
public class BaseEntity {
/**
* Сохраняет сущность в базе данных.
* @param entity Сущность для сохранения.
*/
public void save(Object entity) {
DatabaseManager.save(entity);
}
/**
* Обновляет сущность в базе данных.
* @param entity Сущность для обновления.
*/
public void update(Object entity) {
DatabaseManager.update(entity);
}
/**
* Удаляет сущность из базы данных.
* @param entity Сущность для удаления.
*/
public void delete(Object entity) {
DatabaseManager.delete(entity);
}
}

View File

@@ -0,0 +1,80 @@
package com.rosetta.im.database;
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.List;
public class DatabaseManager {
public static <T> T save(T entity) {
Session session = HibernateUtil.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.persist(entity);
transaction.commit();
return entity;
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
throw new RuntimeException("Error saving entity: " + e.getMessage(), e);
} finally {
session.close();
}
}
public static <T> T update(T entity) {
Session session = HibernateUtil.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.merge(entity);
transaction.commit();
return entity;
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
throw new RuntimeException("Error updating entity: " + e.getMessage(), e);
} finally {
session.close();
}
}
public static <T> T findById(Class<T> entityClass, Long id) {
Session session = HibernateUtil.openSession();
try {
return session.find(entityClass, id);
} finally {
session.close();
}
}
public static <T> List<T> findAll(Class<T> entityClass) {
Session session = HibernateUtil.openSession();
try {
return session.createQuery("FROM " + entityClass.getSimpleName(), entityClass).list();
} finally {
session.close();
}
}
public static <T> void delete(T entity) {
Session session = HibernateUtil.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.remove(entity);
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
throw new RuntimeException("Error deleting entity: " + e.getMessage(), e);
} finally {
session.close();
}
}
}

View File

@@ -0,0 +1,33 @@
package com.rosetta.im.database;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Exception e) {
throw new ExceptionInInitializerError("Error initializing Hibernate: " + e.getMessage());
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
public static Session openSession() {
return sessionFactory.openSession();
}
public static void shutdown() {
sessionFactory.close();
}
}

View File

@@ -0,0 +1,27 @@
package com.rosetta.im.database.converters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
@Converter
public class StringListConverter implements AttributeConverter<List<String>, String> {
@Override
public String convertToDatabaseColumn(List<String> attribute) {
if (attribute == null || attribute.isEmpty()) {
return "";
}
return String.join(",", attribute);
}
@Override
public List<String> convertToEntityAttribute(String dbData) {
if (dbData == null || dbData.isBlank()) {
return new ArrayList<>();
}
return new ArrayList<>(Arrays.asList(dbData.split(",")));
}
}

View File

@@ -0,0 +1,229 @@
package com.rosetta.im.database.entity;
import com.rosetta.im.database.BaseEntity;
import com.rosetta.im.database.HibernateUtil;
import com.rosetta.im.database.converters.StringListConverter;
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity
@Table(name = "users", indexes = {
@Index(name = "idx_users_publickey", columnList = "publicKey", unique = true)
})
public class User extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "privateKey", nullable = false)
private String privateKey;
@Column(name = "username")
private String username;
@Column(name = "title")
private String title;
@Column(name = "publicKey", nullable = false, unique = true)
private String publicKey;
@Column(name = "timestamp", nullable = false)
private long timestamp;
@Column(name = "createdTime", nullable = false, updatable = false)
private Date createdTime;
@Column(name = "verified", nullable = false)
private int verified;
@Convert(converter = StringListConverter.class)
@Column(name = "notificationsTokens", nullable = false)
private List<String> notificationsTokens = new ArrayList<>();
@PrePersist
protected void onCreate() {
createdTime = new Date();
}
@PreUpdate
protected void onUpdate() {
if (createdTime == null) {
createdTime = new Date();
}
}
public Long getId() {
return id;
}
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPublicKey() {
return publicKey;
}
public void setPublicKey(String publicKey) {
this.publicKey = publicKey;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public Date getCreatedTime() {
return createdTime;
}
public int getVerified() {
return verified;
}
public void setVerified(int verified) {
this.verified = verified;
}
public List<String> getNotificationsTokens() {
return notificationsTokens;
}
public void setNotificationsTokens(List<String> notificationsTokens) {
this.notificationsTokens = notificationsTokens;
}
public static User getByPrivateKey(String privateKey) {
try (Session session = HibernateUtil.openSession()) {
return session.createQuery(
"from User where privateKey = :privateKey", User.class)
.setParameter("privateKey", privateKey)
.uniqueResult();
}
}
public static User getByUsername(String username) {
try (Session session = HibernateUtil.openSession()) {
return session.createQuery(
"from User where username = :username", User.class)
.setParameter("username", username)
.uniqueResult();
}
}
public static User getByPublicKey(String publicKey) {
try (Session session = HibernateUtil.openSession()) {
return session.createQuery(
"from User where publicKey = :publicKey", User.class)
.setParameter("publicKey", publicKey)
.uniqueResult();
}
}
public static void addNotificationToken(String privateKey, String token) {
Session session = HibernateUtil.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
User user = session.createQuery(
"from User where privateKey = :privateKey", User.class)
.setParameter("privateKey", privateKey)
.uniqueResult();
if (user != null) {
if (!user.notificationsTokens.contains(token)) {
user.notificationsTokens.add(token);
session.merge(user);
}
}
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
throw new RuntimeException("Error adding notification token: " + e.getMessage(), e);
} finally {
session.close();
}
}
public static void removeNotificationToken(String privateKey, String token) {
Session session = HibernateUtil.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
User user = session.createQuery(
"from User where privateKey = :privateKey", User.class)
.setParameter("privateKey", privateKey)
.uniqueResult();
if (user != null) {
user.notificationsTokens = new ArrayList<>(user.notificationsTokens.stream()
.filter(t -> !t.equals(token))
.toList());
session.merge(user);
}
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
throw new RuntimeException("Error removing notification token: " + e.getMessage(), e);
} finally {
session.close();
}
}
public static List<String> getNotificationTokensByPrivateKey(String privateKey) {
User user = getByPrivateKey(privateKey);
if (user != null) {
return user.notificationsTokens;
}
return List.of();
}
public static List<String> getNotificationsTokensByPublicKey(String publicKey) {
User user = getByPublicKey(publicKey);
if (user != null) {
return user.notificationsTokens;
}
return List.of();
}
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.5//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.5.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/rosetta_db</property>
<property name="hibernate.connection.username">rosetta_user</property>
<property name="hibernate.connection.password">rosetta_password</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!--Зарегистрированные таблицы-->
<mapping class="com.rosetta.im.database.entity.User"/>
</session-factory>
</hibernate-configuration>