Spring JPA findByEmail не работает с присоединением столбца @ManyToMany - PullRequest
2 голосов
/ 10 июля 2020

Как только я добавляю отображение @ManyToOne с @JoinColumn к своей сущности и выполняю производный метод запроса findBy, я получаю исключение org.hibernate.PropertyAccessException: Could not set field value.

ERROR 90376 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Could not set field value [User(name=null, email=email@gmail.com, accountState=ACTIVE, profilePicture=null, otpJsonString=null, company=null)] value by reflection : [class com.example.entity.User.company] setter of com.example.entity.User.company; nested exception is org.hibernate.PropertyAccessException: Could not set field value [User(name=null, email=email@gmail.com, accountState=ACTIVE, profilePicture=null, otpJsonString=null, company=null)] value by reflection : [class com.example.entity.User.company] setter of com.example.entity.User.company] with root cause

java.lang.IllegalArgumentException: Can not set com.example.entity.Company field com.example.entity.User.company to com.example.entity.User
package com.example.entity;

import lombok.*;

import javax.persistence.*;

@Entity
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity {

    @Id
    @GeneratedValue
    @Basic(optional = false)
    private Long id;
}

package com.example.entity;

import lombok.*;
import lombok.experimental.SuperBuilder;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.Instant;

@Getter
@Setter
@ToString
@MappedSuperclass
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable<T> extends BaseEntity {

    @CreatedBy
    protected T createdBy;
    @CreatedDate
    protected Instant createdAt;
    @LastModifiedBy
    protected T lastModifiedBy;
    @LastModifiedDate
    protected Instant lastModifiedAt;

    public Auditable(Long id) {
        super(id);
    }
}

package com.example.entity;

import lombok.*;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import javax.persistence.*;
import java.io.Serializable;

@Getter
@Setter
@Entity
@ToString
@EqualsAndHashCode
@NoArgsConstructor
public class User extends Auditable<String> implements Serializable {

    @NonNull
    private String name;
    @NonNull
    private String email;
    @NonNull
    private String accountState; //ACTIVE, BLOCKED, DELETED
    private String profilePicture;
    private String otpJsonString;
    @ManyToOne(optional = false)
    @JoinColumn(name = "Company_Id", referencedColumnName = "Id")
    private Company company;

    public User(Long id, String name, String email, Company company,
                String profilePicture, String accountState, String otpJsonString) {
        super(id);
        this.name = name;
        this.email = email;
        this.accountState = accountState;
        this.company = company;
        this.profilePicture = profilePicture;
        this.otpJsonString = otpJsonString;
    }
}

package com.example.entity;

import lombok.*;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;

@Getter
@Setter
@Entity
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@Table(indexes = {
        @Index(name = "website_unq_idx", columnList = "website", unique = true),
        @Index(name = "emailDomain_unq_idx", columnList = "emailDomain", unique = true),
})
public class Company extends Auditable<String> implements Serializable {

    @NonNull
    private String name;
    @NonNull
    private String logo;
    @NonNull
    private String website;
    @NonNull
    private String accountState; //ACTIVE, BLOCKED, DELETED
    @NonNull
    private String emailDomain;

    public Company(Long id, String name, String logo, String website, String accountState,
                                    String emailDomain) {
        super(id);
        this.name = name;
        this.logo = logo;
        this.website = website;
        this.accountState = accountState;
        this.emailDomain = emailDomain;
    }
}

Вот запускается весенний запрос:

Hibernate: 
    select
        user0_.id as id1_0_,
        user0_.created_at as created_1_4_,
        user0_.created_by as created_2_4_,
        user0_.last_modified_at as last_mod3_4_,
        user0_.last_modified_by as last_mod4_4_,
        user0_.account_state as account_5_4_,
        user0_.email as email6_4_,
        user0_.company_id as comp_ch10_4_,
        user0_.name as name7_4_,
        user0_.otp_json_string as otp_json8_4_,
        user0_.profile_picture as profile_9_4_ 
    from
        user user0_ 
    where
        user0_.email=? 
        and user0_.account_state<>?
package com.example.repository;

import com.example.entity.User;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
   
    Optional<User> findByEmailAndAccountStateNot(String email, String accountState);
}

1 Ответ

1 голос
/ 10 июля 2020

Для optional in do c

Является ли ассоциация необязательной. Если установлено значение false, всегда должно существовать ненулевое отношение.

Итак, для optional = false JPA ожидает, что в базе данных всегда будут предоставляться данные для этого объекта. Удалите это, чтобы не отображать Company Объект

...