原创

导致:org.hibernate.HibernateException:非法尝试将一个集合与两个打开的集合关联起来

温馨提示:
本文最后更新于 2024年04月12日,已超过 48 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

I am in the process of creating a minecraft plugin. For this project, I am using a small library called Spigot Injection (https://github.com/hakan-krgn/spigot-injection), probably wasn't a good idea, but it works fairly well and simplies the code alot anyway.

I am using hibernate to connection to a database. And using there sort of repositories thing. To save and create data. Here are my two schemas in question: FactionEntity.class

@Data
@Table(name = "Factions")
@Entity
public class FactionEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, unique = true)
    private Long id;

    @Column(name = "name", nullable = false, unique = true)
    private String name;

    @Column(name = "description")
    private String description;

    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "x", column = @Column(name = "centerX")),
            @AttributeOverride(name = "y", column = @Column(name = "centerY")),
            @AttributeOverride(name = "z", column = @Column(name = "centerZ"))
    })
    private Position center;

    @OneToMany(mappedBy = "faction")
    private Set<MemberEntity> members;

    @OneToMany(mappedBy = "claimedBy")
    private Set<ChunkEntity> claims;
}

ChunkEntity.class

@Data
@Table(name = "Chunks")
@Entity
public class ChunkEntity {
   @Id
   @Column(name = "id", nullable = false, unique = true)
   private Long id;

   @Column(name = "x", nullable = false)
   private int x;

   @Column(name = "z", nullable = false)
   private int z;

   @ManyToOne
   @JoinColumn(name = "faction_id")
   private FactionEntity claimedBy;

   @Column(name = "value", nullable = false)
   private Long value = 0L;
}

Now I have this big code block which does some processing, I will upload this to a snippet. But basically I am getting the faction, updating some properties. saving it.

Then created some chunk entites which reference the faction entity. When I run this I get the following error:

Caused by: org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions: Collection : [dev.jpac14.spigotinjection.model.FactionEntity.claims#1]
        at org.hibernate.collection.spi.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:728) ~[SpigotInjection-1.0-SNAPSHOT-all.jar:?]

When looking at the library, I notice that the JpaRepository I extend in my repositoru doesn't have a merge or refresh implementation. Since I am using spigot injection those implementation are hard set and I can't really change them unless I fork it and change the code which might be a last alternative to change the code.

Calling code Calling code

@EventListener
    public void onBlockPlace(BlockPlaceEvent event) {
        Player player = event.getPlayer();
        Block block = event.getBlock();
        World world = block.getWorld();

        // check if player is in faction
        MemberEntity member = memberRepository.findById(player.getUniqueId());
        FactionEntity faction = member.getFaction();

        // TODO: check if in a 3x3 radius, of another faction

        // update center position
        faction.setCenter(Position.fromBlock(block));
        faction = factionsRepository.save(faction);

        Chunk chunk = block.getChunk();
        int x = chunk.getX();
        int z = chunk.getZ();

        List<ChunkEntity> neighbours = new ArrayList<>();

        // claim nearby chunks in 3x3 (1 radius)
        // could be expensive operation
        for (int i = x - RADIUS; i < x + RADIUS; i++) {
            for (int j = z - RADIUS; j < z + RADIUS; j++) {
                ChunkEntity nearby = new ChunkEntity();
                Long key = Chunk.getChunkKey(i, j);

                nearby.setId(key);
                nearby.setX(i);
                nearby.setZ(j);
                nearby.setClaimedBy(faction);

                // get value of chunk
                AtomicReference<Long> total = new AtomicReference<>((long) 0);
                forEachBlockInChunk(world, i, j, (b) -> {
                    Integer value = blockValues.get(b.getType());
                    if (value == null) return;
                    total.updateAndGet((v) -> v + value);
                });

                nearby.setValue(total.get());

                neighbours.add(nearby);
            }
        }

        // save each to DB; TODO: is there a save all?
        neighbours.forEach(this.chunkRepository::save);

        player.sendMessage("This is now the centre of your faction.");
    }

I have tried moving some statements, around. But not sure what else do without refresh and merge. I am definitely doing some wrong that is simple.

Any help appreciated

正文到此结束
热门推荐
本文目录