简体   繁体   中英

Lazy One-to-one Optional Bidirectional Mapping using Hibernate annotations

I want to create a Lazy One-to-one Bidirectional 'Optional' Mapping using Hibernate annotations. I know that the normal usage of @MappedBy and @JoinColumn result in N+1 queries being fired every time.

Is there a way I can avoid this? Not just at runtime, but at the POJO level. I am using Hibernate 4.3 , so can't think about bytecode enhancement.

Further, if there is no way out, is it possible to apply criteria on unidirectional mappings. For example, I have A <-> B, and C -> A as mappings. And I am searching on B . Is it possible to apply a restriction on C when C is clearly unidirectional with A ?

The @OneToOne annotaion doesn't work in hibernate as needed. Please consider the @LazyToOne or try using @OneToMany like @OneToOne . Also you can attempt @PrimaryKeyJoinColumn .

ps The @LazyToOne annotation doesn't exist in JPA realization, you should use @OneToOne(fetch = FetchType.LAZY, optional = false) there

I could not find a complete but minimal examples of LAZY bidirectional @OneToOne , so here it is. It is neither hibernate-version-dependent nor does it misuse @OneToMany .

Parent

Defines the id and is responsible for managing the consistency/synchronization, but technically does not own the relationship, because it can not reference any unique index in B (or at least we do not want to add redundant data).

@Entity
public class A {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(
            mappedBy = "a",
            cascade = CascadeType.ALL,
            orphanRemoval = true,
            fetch = FetchType.LAZY
    )
    private B b;

    public void setB(B b) {
        if (b == null) {
            if (this.b != null) {
                this.b.setA(null);
            }
        } else {
            b.setA(this);
        }
        this.b = b;
    }
    // ... other setters/getters
}

Child

Technically owns the relationship by re-using the id of parent A .

@Entity
public class B {
    @Id
    // Not generated but shared with A
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    @JoinColumn(name = "id") // otherwise use "a_id" instead of "id" in the DB column
    private A a;
    // ... other setters/getters
}

And this is how the tables should look like (assuming postgres):

CREATE TABLE a (
    id bigint NOT NULL PRIMARY KEY,
);

CREATE TABLE b (
    id bigint NOT NULL PRIMARY KEY,
    FOREIGN KEY (id) REFERENCES a(id);
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM