spring Hibernate @OneToMany注解似乎不起作用

vfwfrxfs  于 2023-05-16  发布在  Spring
关注(0)|答案(1)|浏览(222)

我试图获取我的“票”实体与我的“文件数据”包括在内,但我不能让它工作,我完全不知道为什么。其他人的代码似乎和我自己的代码一样工作得很好。但是无论何时获取它,我的“Ticket”对象的“files”列都返回空的。
(and是的,数据库中有它的数据,所以与给定ID相关联的列不是null或类似的值)
我的BaseEntity类包括@Id注解、创建日期、修改日期、用户创建日期等。
票证实体:

package com.issue.tracker.ticket;

import com.issue.tracker.common.BaseEntity;
import com.issue.tracker.filesystem.FileData;
import com.issue.tracker.project.Project;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.HashSet;
import java.util.Set;

@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "tickets")
public class Ticket extends BaseEntity {

    @NotEmpty
    private String issueName;

    @NotEmpty
    private String description;

    @ManyToOne
    @JoinColumn(name="project_id", nullable=false)
    private Project project;

    //This is supposed to work but for some reason it doesn't seem to
    @OneToMany(mappedBy = "ticket", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<FileData> files = new HashSet<>();
}

文件数据实体:

package com.issue.tracker.filesystem;

import com.issue.tracker.common.BaseEntity;
import com.issue.tracker.ticket.Ticket;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "file_datas")
@AllArgsConstructor
@NoArgsConstructor
public class FileData extends BaseEntity {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="ticket_id", nullable=false)
    private Ticket ticket;

    @NotEmpty
    private String filePath;

    @NotEmpty
    private String fileName;

    @NotEmpty
    private String fileType;

    @NotNull
    private Long fileSize;
}

TicketRepository:

package com.issue.tracker.ticket;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface TicketRepository extends JpaRepository<Ticket, Long> {

    List<Ticket> findAllByCreatedBy(String username);
}

TicketServiceImpl(包括注解掉的部分,我得到一个空的“files”列):

package com.issue.tracker.ticket;

import com.issue.tracker.common.RollbackOnException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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

@Slf4j
@RequiredArgsConstructor
@Service
public class TicketServiceImpl implements TicketService {

    private final TicketRepository ticketRepository;

    @RollbackOnException
    @Override
    public Ticket createTicket(Ticket ticket) {
        return ticketRepository.save(ticket);
    }

    @Override
    public List<Ticket> getAllTicketsByName(String username) {
        return ticketRepository.findAllByCreatedBy(username);
    }

    @Override
    public List<Ticket> getAllTickets() {
        return ticketRepository.findAll();
    }

    @Override
    public Ticket getTicketById(Long id) {
        Ticket ticket = ticketRepository.findById(id).orElseThrow(() -> new NoSuchElementException("Ticket not found"));
        log.info(ticket.toString());
    //this is what I get here, note that "files" is empty:
    //Ticket(issueName=AAAAAAAAAA...
    //description=ahdfjduafadjfhadjfhadjfhadjfhadjlfhadjfadjfhad,
    //project=Project(projectName=Webshop), files=[])
        return ticket;
    }
}

我对SQL日志很好奇,这是在后台发生的hibernate魔术:

select
    t1_0.id,
    t1_0.created_at,
    t1_0.created_by,
    t1_0.description,
    t1_0.issue_name,
    t1_0.modified_by,
    p1_0.id,
    p1_0.created_at,
    p1_0.created_by,
    p1_0.modified_by,
    p1_0.project_name,
    p1_0.updated_at,
    t1_0.updated_at
from tickets t1_0 join projects p1_0 on p1_0.id=t1_0.project_id
where t1_0.id=?

select f1_0.ticket_id,
f1_0.id,
f1_0.created_at,
f1_0.created_by,
f1_0.file_name,
f1_0.file_path,
f1_0.file_size,
f1_0.file_type,
f1_0.modified_by,
f1_0.updated_at
from file_datas f1_0
where f1_0.ticket_id=?

select f1_0.ticket_id,
f1_0.id,
f1_0.created_at,
f1_0.created_by,
f1_0.file_name,
f1_0.file_path,
f1_0.file_size,
f1_0.file_type,
f1_0.modified_by,
f1_0.updated_at
from file_datas f1_0
where f1_0.ticket_id=?

我的file_datas部分被单独调用了两次。我猜了两次,因为有两行对应于给定的ticket_id。我已经包括了一些数据的图片和表之间的连接。

更新

还是不管用

public TicketDataDto getTicketById(@PathVariable Long id) {

    Ticket ticket = ticketService.getTicketById(id);
    ticket.getFiles();
    log.info(ticket.toString());

    return modelMapper.map(ticket, TicketDataDto.class);
}

简单地调用ticket.getFiles()不会做任何事情,它仍然是空的。
将其修改为

public TicketDataDto getTicketById(@PathVariable Long id) {

    Ticket ticket = ticketService.getTicketById(id);
    var files = ticket.getFiles();
    log.info(files.toString());

    return modelMapper.map(ticket, TicketDataDto.class);
}

也不管用。将Ticket实体的fetchtype更改为fetch=FetchType.EAGER不能解决这个问题。

UPDATE 2从Ticket实体中删除@Data并创建自己的toString也没有帮助,每次都是相同的响应。

@Override
public String toString() {
    return "Ticket{" +
            "issueName='" + issueName + '\'' +
            ", description='" + description + '\'' +
            ", project=" + project +
            ", files=" + files +
            '}';
}

这个toString生成:

Ticket{issueName='AAAAAAAAAAAAAAAAAAAAA',  description='ahdfjduafadjfhadjfhadjfhadjfhadjlfhadjfadjfhad', project=Project(projectName=Webshop), files=[]}

更新3

5gfr0r5j

5gfr0r5j1#

你的“files”属性应该是空的,因为你是这样定义的:fetch = FetchType.LAZY
然后,如果你调用getFiles在您检索的票,它将获取文件。

相关问题