简体   繁体   中英

Prevent hibernate from selecting children when updating its parent?

The Problem

When I update my parent class, hibernate selects all its child before triggering the update. This only happens when we added new children that are not persistent in the database yet. Hibernate selects those children one by one, which is very... very slow.

Batching is already enabled and working for normal inserts, updates and removals. I gave the child a version, which hibernates ignores somehow.

select * from identity...
select * from identity...
select * from identity...
select * from identity...
insert .... into identity...
update chunk set ....

Question

Is there a way to either make hibernate batch those selects or to implement some other mechanic in which hibernate simply checks the added child if its new without selecting it from the database first?

I basically want to get rid of those "one by one" selects. Would be glad for any help I can get.

My Classes

When I update chunk which contains multiple identities that are not yet in the database ( inChunk )... it tries to determine if they are in the database which results in one select for each child to filter those children that are need to get inserted... how do I prevent those many selects? I still want to keep the cascading.

@Entity
@Access(AccessType.FIELD)
@SQLInsert(sql = "insert into identity(tag, typeID, id, version) values(?,?,?,?) ON DUPLICATE KEY UPDATE id = VALUES(id), tag = values(tag), typeID = values(typeID), version = values(version)")
@SelectBeforeUpdate(value = false)
public class Identity extends Component {

    @Id public long id;
    public String tag;
    public String typeID;

    @Version public long version;
}

@Entity
@Table(name = "chunk", uniqueConstraints = {@UniqueConstraint(columnNames={"x", "y"})}, indexes = {@Index(columnList = "x,y")})
@Access(value = AccessType.FIELD)
@SelectBeforeUpdate(false)
public class Chunk extends HibernateComponent {

    public int x;
    public int y;
    public Date createdOn;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Fetch(FetchMode.JOIN)
    @BatchSize(size = 50)
    public Set<Identity> inChunk = new LinkedHashSet<>();
}

Unidirectional one-to-many association - is not good practice. I would recommend to define the many-to-one association in the Identity class, then add the mappedBy attribute to the @OneToMany annotation on the inChunk field, and then fetch Chunk.inChunk association before add new children.

@Entity
@Access(AccessType.FIELD)
@SQLInsert(sql = "insert into identity(tag, typeID, id, version) values(?,?,?,?) ON DUPLICATE KEY UPDATE id = VALUES(id), tag = values(tag), typeID = values(typeID), version = values(version)")
@SelectBeforeUpdate(value = false)
public class Identity extends Component {

    @Id public long id;
    public String tag;
    public String typeID;

    @Version public long version;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "chunk_id") // I suppose the Chunk entity has id
    public Chunk chunk;
}

@Entity
@Table(name = "chunk", uniqueConstraints = {@UniqueConstraint(columnNames={"x", "y"})}, indexes = {@Index(columnList = "x,y")})
@Access(value = AccessType.FIELD)
@SelectBeforeUpdate(false)
public class Chunk extends HibernateComponent {

    public int x;
    public int y;
    public Date createdOn;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "chunk")
    @Fetch(FetchMode.JOIN)
    @BatchSize(size = 50)
    public Set<Identity> inChunk = new LinkedHashSet<>();
}

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