Ошибка IllegalArgumentException в Hibernate

При добавлении клиента в БД вылетает ошибка IllegalArgumentException. Класс ClientDetails

import com.example.BankService.model.Client;
import lombok.*;

import javax.persistence.*;


@Getter
@Setter
@Table(name = "clients_details")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class ClientDetails{
    @Column(name = "id")
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long ID;

    @Embedded
    private Client client;
}

Класс Client

import lombok.*;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import java.time.LocalDate;

@Getter
@Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class Client {
    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "father_name")
    private String fatherName;

    @Column(name = "phone")
    private String phone;

    @Column(name = "email")
    private String email;

    @Column(name = "username")
    private String username;

    @Column(name = "password")
    private String password;

    @Column(name = "birth_day")
    //@BirthDate(message = "Incorrect year")
    private LocalDate birthDay;

    @Column(name = "roles")
    private String roles;

    @Embedded
    private BankAccount bankAccount;
}

Класс BankAccount

import lombok.*;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Getter
@Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class BankAccount {
    @Column(name = "bank_account_id")
    private Long id;
    @Column(name = "initial_balance")
    private float initialBalance;
    @Column(name = "balance")
    private float accountBalance;

}

Класс ClientDAOImpl

import com.example.BankService.entity.ClientDetails;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.transaction.Transactional;
import java.util.List;

@Repository
public class ClientDAOImpl implements ClientDAO{
    @Autowired
    Session session;


    @Override
    @Transactional
    public void addClient(ClientDetails clientDetails) {
        //Session session = getSession();
        session.beginTransaction();
        session.save(clientDetails);
        session.close();
    }

    @Override
    @Transactional
    public ClientDetails findByUsername(String username) {
        //Session session = getSession();
        session.beginTransaction();
        Query query = session.createQuery("FROM ClientDetails WHERE username = :username");
        query.setParameter("username", username);
        ClientDetails clientDetails = (ClientDetails) query.uniqueResult();
        session.getTransaction().commit();
        return clientDetails;
    }

    @Override
    @Transactional
    public void updateClient(ClientDetails clientDetails) {
        //Session session = getSession();
        session.beginTransaction();
        session.update(clientDetails);
        session.getTransaction().commit();
    }

    @Override
    @Transactional
    public void deleteClient(ClientDetails clientDetails) {
        //Session session = getSession();
        session.beginTransaction();
        session.delete(clientDetails);
        session.close();
    }

    @Override
    @Transactional
    public ClientDetails getClientDetailsById(long id) {
       // Session session = getSession();
        session.beginTransaction();
        return session.get(ClientDetails.class, id);
    }

    public ClientDetails getClientDetailsByEmail(String email) {
        var clients = getAllClientDetails();
        for (ClientDetails client : clients){
            if (client.getClient().getEmail().equals(email)){
                return client;
            }
        }
        return null;
    }

    @Override
    @Transactional
    public List<ClientDetails> getAllClientDetails() {
        List<ClientDetails> clientDetailsList = session.createQuery("from ClientDetails").getResultList();
        return clientDetailsList;
    }
}

Класс RegisterController

@Controller
@RequestMapping("/register")
public class RegisterController {
    private final RegisterProcessor registerProcessor;
    private final BankAccountService bankAccountService;
    private final LoginManagerService loginManagerService;
    private final ClientDAOImpl clientDAOImpl;

    private final PasswordEncoder passwordEncoder;

    @Autowired
    public RegisterController(RegisterProcessor registerProcessor,
                              BankAccountService bankAccountService,
                              LoginManagerService loginManagerService,
                              ClientDAOImpl clientDAOImpl, PasswordEncoder passwordEncoder) {
        this.registerProcessor = registerProcessor;
        this.bankAccountService = bankAccountService;
        this.loginManagerService = loginManagerService;
        this.clientDAOImpl = clientDAOImpl;
        this.passwordEncoder = passwordEncoder;
    }

    @GetMapping
    public String register(Model model) {
        model.addAttribute("client", new Client());
        return "register.html";
    }

    @PostMapping
    public String newRegister(@ModelAttribute("client") Client client,
                              Model model) {
        registerProcessor.setEmail(client.getEmail());
        boolean register = registerProcessor.register();
        if (register) {
            client.setPassword(passwordEncoder.encode(client.getPassword()));
            client.setRoles("ROLE_USER");
            BankAccount bankAccount = bankAccountService.createBankAccount();
            client.setBankAccount(bankAccount);
            ClientDetails clientDetails = new ClientDetails();
            clientDetails.setClient(client);
            clientDAOImpl.addClient(clientDetails);
            loginManagerService.setID(client.getBankAccount().getId());
            var clients = clientDAOImpl.getAllClientDetails();
            model.addAttribute("clients", clients);
            return "redirect:/login";
        } else {
            model.addAttribute("message", "A user with this email address already exists");
            return "register.html";
        }
    }
}

Класс RegisterProcessor

@Component
@RequestScope
@Data
public class RegisterProcessor {
    private ClientService clientService;
    private LoginManagerService loginManagerService;
    private String email;
    @Autowired
    public RegisterProcessor(ClientService clientService, LoginManagerService loginManagerService) {
        this.clientService = clientService;
        this.loginManagerService = loginManagerService;
    }

    public boolean register(){
        var clients = clientService.findAll();
        boolean notRegister = false;
        for (Client client : clients){
            if(email.equals(client.getEmail())){
                return false;
            }
        }
        loginManagerService.setEmail(email);
        notRegister = true;
        return notRegister;
    }
}

Класс HibernateConfig

@Configuration
public class HibernateConfig {
    @Bean
    public Session getSession(){
        SessionFactory factory = new org.hibernate.cfg.Configuration().configure("hibernate.cfg.xml")
                .addAnnotatedClass(ClientDetails.class).buildSessionFactory();
        return factory.openSession();
    }
}

Файл hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="connection.url">jdbc:postgresql://localhost:5432/postgres</property>
        <property name="connection.username">postgres</property>
        <property name="connection.password">1</property>
        <property name="current_session_context_class">jta</property>
        <property name="connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQL10Dialect</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        
        <mapping class="com.example.BankService.entity.ClientDetails"/>
    </session-factory>

</hibernate-configuration>

Ну и стек ошибок (весь список не стал копировать, очень много места занимает)

2024-04-02T21:43:04.376+07:00 ERROR 12420 --- [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private com.example.BankService.model.Client com.example.BankService.entity.ClientDetails.client] by reflection for persistent property [com.example.BankService.entity.ClientDetails#client] : ClientDetails(ID=null, client=Client(firstName=NIKOLAY, lastName=LABAZOV, fatherName=Konstantinovich, phone=89998586563, [email protected], username=qqqqq, password=$2a$10$nySaNfQzjp.MaAfgK6udTuTIJtMNNaX8rzL0iqAvaC8F5wDaJD0Fm, birthDay=1996-01-13, roles=ROLE_USER, bankAccount=BankAccount(id=108449914, initialBalance=13184.117, accountBalance=13184.117)))] with root cause

java.lang.IllegalArgumentException: Can not set com.example.BankService.model.Client field com.example.BankService.entity.ClientDetails.client to com.example.BankService.entity.ClientDetails
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36) ~[na:na]
    at java.base/java.lang.reflect.Field.get(Field.java:425) ~[na:na]
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:71) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.property.access.spi.GetterFieldImpl.getForInsert(GetterFieldImpl.java:90) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValuesToInsert(AbstractEntityTuplizer.java:603) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.tuple.entity.PojoEntityTuplizer.getPropertyValuesToInsert(PojoEntityTuplizer.java:164) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValuesToInsert(AbstractEntityPersister.java:5377) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:265) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:122) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:194) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:179) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:75) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:672) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:665) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:660) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at com.example.BankService.dao.ClientDAOImpl.addClient(ClientDAOImpl.java:23) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.4.jar:6.1.4]
    at com.example.BankService.dao.ClientDAOImpl$$SpringCGLIB$$0.addClient(<generated>) ~[classes/:na]
    at com.example.BankService.controller.RegisterController.newRegister(RegisterController.java:56) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]

В данном стеке ругается больше всего на метод save() класса ClientDAOImpl, хотя я не понимаю, что не так

Также стек ошибок, который указывает на то, что невозможно "достучаться" до поля ID класса ClientDetails

java.lang.IllegalArgumentException: Can not set java.lang.Long field com.example.BankService.entity.ClientDetails.ID to com.example.BankService.entity.ClientDetails
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36) ~[na:na]
    at java.base/java.lang.reflect.Field.get(Field.java:425) ~[na:na]
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:71) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:231) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:5309) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:76) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:207) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:166) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:229) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:93) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1372) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1452) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1649) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at org.hibernate.query.Query.getResultList(Query.java:165) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    at com.example.BankService.dao.ClientDAOImpl.getAllClientDetails(ClientDAOImpl.java:83) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.4.jar:6.1.4]
    at com.example.BankService.dao.ClientDAOImpl$$SpringCGLIB$$0.getAllClientDetails(<generated>) ~[classes/:na]

Здесь компилятор ругается на метод getAllClientDetails()

Также класс BankServiceApplication

@SpringBootApplication
public class BankServiceApplication {

    public static void main(String[] args) {
        System.setProperty("javax.xml.bind.context.factory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
        SpringApplication.run(BankServiceApplication.class, args);
    }
}

Здесь костыль в виде System.setProperty..., который я применил по совету GPT, так как без него вылетало следующее

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig' defined in file [C:\Users\sesor\OneDrive\Рабочий стол\Programming\TestCase\BankService\target\classes\com\example\BankService\configurations\SecurityConfig.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'clientDAOImpl': Unsatisfied dependency expressed through field 'session': Error creating bean with name 'getSession' defined in class path resource [com/example/BankService/configurations/HibernateConfig.class]: Failed to instantiate [org.hibernate.Session]: Factory method 'getSession' threw exception with message: Unable to perform unmarshalling at line number 0 and column 0 in RESOURCE hibernate.cfg.xml. Message: null

Вот класс SecurityConfig

@Configuration
@ComponentScan(basePackages = "com.example")
public class SecurityConfig {
    @Autowired
    private ClientDAO clientDAO;

    public SecurityConfig(ClientDAO clientDAO) {
        this.clientDAO = clientDAO;
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    public UserDetailsService userDetailsService(ClientDAO clientDAO){
        return new ClientService(clientDAO);
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((autorize) -> autorize
                        .requestMatchers("/edit", "/withdraw", "/transfer", "/home").authenticated()
                        .requestMatchers("/login", "/register").permitAll())
                .formLogin(form -> form.loginPage("/login")
                        .defaultSuccessUrl("/home")).logout(logout -> logout.logoutSuccessUrl("/login"));
        return http.build();
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService(clientDAO));
        provider.setPasswordEncoder(passwordEncoder());
        return provider;
    }

}

Ответы (0 шт):