JPA @OneToMany:外键为空。

5
我需要帮助正确定义@OneToMany JPA注释。尝试了不同的方法,但仍然出现错误/问题,例如visitorCharacteristic表中的外键(visitor_revision_id)为空。
我想用"visitor_revision_id"将这2个表连接起来。
@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
@ToString
public class Visitor {
    @Id
    @Column(name="visitor_revision_id")
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    Long id;

    String visitorCode;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "visitor")
    List<VisitorCharacteristic> visitorCharacteristicList;
}

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
@ToString
class VisitorCharacteristic {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    Long id;

    @JoinColumn(name = "visitor_revision_id")
    @ManyToOne(optional = false) //fetch = FetchType.EAGER, cascade =  CascadeType.ALL)
    Visitor visitor;

    @Column(nullable = false)
    String attributeCode;

    @Column(nullable = false)
    String attributeValue;    
}

提前感谢您的帮助。

你能提供一个单元测试的例子来展示失败吗? - Bob Lukens
谢谢您的快速回复!我不知道我需要手动设置VisitorCharacteristic#visitor。 - GeorgesD
5个回答

10

JPA不会自动为您设置VisitorCharacteristic#visitor字段,您需要手动设置。如果您有一些添加后续VisitorCharacteristic的方法,则还应将设置特征中的visitor的代码添加进去:

public void addVisitorCharacteristic(VisitorCharacteristic visitorCharacteristic) {
    if (visitorCharacteristicList == null) {
        visitorCharacteristicList = new ArrayList<>();
    }
    visitorCharacteristic.visitor = this;
    visitorCharacteristicList.add(visitorCharacteristic);
}

这里有一个包含您的代码并且能够正常运行的Gist - 请查看第79行。


1
您可以通过以下方式进行注释来实现:

@RepositoryRestResource(export = false)VisitorCharacteristicRepository

并为 VisitorCharacteristic 创建自己的自定义控制器。

要了解更多信息,请参见 - https://youtu.be/FRvtVf9sVjs


1
没有一个展示失败的测试用例,很难确定原因。
以下是一些您可以尝试的方法:
  1. VisitorCharacteristic 的连接列注释中添加 , nullable = false

  2. 在两个方向上设置关系 Visitor v = new Visitor(); VisitorCharacteristic vc = new VisitorCharacteristic(); v.setVisitorCharacteristicList(Arrays.asList(vc)); vc.setVisitor(v);


无法工作... - Wood
我认为这只有在VisitorCharacteristic没有Visitor属性时才有效。因为这正是我想要的,所以我给它一分。 - mari

1
访问者类
public class Visitor {
    @Id
    @Column(name = "visitor_revision_id")
    @GeneratedValue
    Long id;

    @Column
    String visitorCode;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "visitor_revision_id", referencedColumnName = "visitor_revision_id")
    List<VisitorCharacteristic> visitorCharacteristicList;
}

访问者特征
public class VisitorCharacteristic {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    @Column
    String attributeCode;
    @Column
    String attributeValue;
}

0
我有两个表:用户和钱包。我想使用FK关系将这两个表链接起来,并且我正在使用带有Repository模式的Hibernate。
当我进行以下操作时,我会得到以下错误: ERROR: null value in column "user_id" of relation "wallet" violates not-null constraint
详细信息:[请求处理失败;嵌套异常是org.springframework.dao.DataIntegrityViolationException:无法执行语句;SQL [n / a];约束[user_id" of relation "wallet]; 嵌套异常是org.hibernate.exception.ConstraintViolationException:无法执行语句]
    Wallet wallet = new Wallet();
    wallet.setAccountsSet(Set.of("creditAccount", "debitAccount"));

    Users user = UsersMapper
            .dtoToEntity(usersDto       
            .setWalletDtoSet(
              Set.of(WalletMapper.entityToDto(wallet)))
            );
   
    this.usersRepository.save(user);

根本原因:钱包表中的外键没有非空约束。移除非空约束解决了违反约束的问题 - user_id 为空

表:

CREATE TABLE public.users (
id varchar NOT NULL,
is_active bool NOT NULL DEFAULT true,
created_by varchar NOT NULL,
creation_timestamp timestamptz NOT NULL DEFAULT now(),
updated_by varchar NULL,
update_timestamp timestamptz NOT NULL DEFAULT now(),
CONSTRAINT users_uuid_pk PRIMARY KEY (uuid)
);


CREATE TABLE public.wallet (
wallet_id int4 NOT NULL GENERATED BY DEFAULT AS IDENTITY,
user_id varchar NULL,
CONSTRAINT wallet_wallet_id_pk PRIMARY KEY (wallet_id),
CONSTRAINT wallet_user_uuid_fk FOREIGN KEY (user_uuid) REFERENCES public.users(uuid)
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接