Задать вопрос
@svema0705

Почему hibernate пытается записать строку с пустыми значениями?

Нужно вставить в базу строку, в которой находится id, ник и почта. Для этого я создаю объект, задаю свойства его полей и затем вызываю метод save
SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        psqlRow newUser = new psqlRow();
        newUser.setId((long)102); //Ид пользователей из другой команды начинается с 100, и таблица имеет секции соразмерные 100
        newUser.setNickname("svema0705");
        newUser.setEmail("svema0705@mail.mail");
        newUser.setFirstname("Ilya");

        logger.info(" " + newUser.getId() + " " + newUser.getNickname() + " " + newUser.getFirstname() + " " + newUser.getEmail());
        session.save(newUser);
        session.flush();

        transaction.commit();
        session.close();
        sessionFactory.close();


На этом месте в логах видно, что hibernate сформировал пустой запрос:

03:21:15 [INFO ] >>  102 svema0705 Ilya svema0705@mail.mail
Hibernate: 
    insert 
    into
        acman.accounts
        (email, nickname, firstname) 
    values
        (?, ?, ?)
03:21:15 [WARN ] >> SQL Error: 0, SQLState: 23514
03:21:15 [ERROR] >> ОШИБКА: для строки не найдена секция в отношении "accounts"
  Подробности: Ключ секционирования для неподходящей строки содержит (id) = (null).


Гугление более старых вопросов, насколько хватило активного словаря инглиша, хватило на несколько общих решений, которые к сожалению не помогли. В самой бд я держу одну строку, которая успешно читается, но вот записать я почему-то не могу

Класс, которым мапится база крайне прост:
import lombok.*;

import javax.persistence.*;
import java.sql.Timestamp;

@Entity
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Table(name="accounts", schema = "acman")
public class psqlRow
{
    @Getter
    @Setter
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long uid = null;

    @Getter
    @Setter
    @Basic
    @Column(name = "email")
    public String email = null;

    @Getter
    @Setter
    @Basic
    @Column(name = "nickname")
    public String nickname = null;

    @Getter
    @Setter
    @Basic
    @Column(name = "firstname")
    public String firstname = null;
}


Конфиг hibernate. Поля логина, пароля и адреса базы задаются программно

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection properties -->
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.url">jdbc:postgresql://192.168.7.231:36000/accounts</property>
        <!-- Other Hibernate properties -->
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQL95Dialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="format_sql">true</property>
        <!-- first time it is create and the onwards update -->
        <property name="hbm2ddl.auto">update</property>
        <property name="hibernate.ejb.naming_strategy"></property>
        <!-- Mapping files or annotated classes -->
        <!-- Add your entry classes or mapping files here for ex: entity used below -->
        <mapping class="Sv.Psql.PostgresManager"/>
    </session-factory>
</hibernate-configuration>


Что нужно дописать или хотя бы как отследить, почему значения полей пропадают при формировании запросов в базу? Я только начал изучать hibernate и стараюсь не писать "замороченный" код чтобы было легко понять
  • Вопрос задан
  • 84 просмотра
Подписаться 1 Простой 9 комментариев
Решения вопроса 1
xez
@xez Куратор тега Java
TL Junior Roo
Для начала, я бы разобрался с классом psqlRow. Ужас, кровь из глаз.
0. Имя класса пишется с большой буквы, имя переменной - с маленькой.
1. Разберитесь с ломбоком. Не нужно аннотации лепить в неограниченно колличестве. Если вы объявили Setter и
@Getter над классом, не нужно повторно их объявлять над переменной.
2. Используйте record для DTO, по возможности.
3. Не нужно, без необходимости добавлять "= null" к каждой переменной. Нулов вообще следует избегать.
4. Тут вот самое непонятное место:
@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long uid = null;

а. Почему uid, а не id, хотя даже в коде у вас setId? (другой какой-то класс?)
б. nullable = false, но при этом дополнительно uid = null (wtf?!)
в. @GeneratedValue, но при этом вы пытаетесь что-то в него засетить.

5. Скорее всего, проблема в том, что инсерт у вас такой:
insert into acman.accounts
        (email, nickname, firstname) -- нет id
    values
        (?, ?, ?)

id предполагается будет установлен автоинкрементом силами самой БД (значение автоикремента, кстати, не имеет отношения к уже заполненным данным), и там либо ничего не заполняется (например, потому, что при создании таблицы не объявлен автоинкремент на поле), либо заполняется, чем-то, что не соответствует правилам секционирования.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы