JPA Hibernate ManyToMany创建关系

时间:2016-03-17 15:19:14

标签: java hibernate jpa

JPA在Wildfly 9上使用Hibernate。

我有2个ManyToMany

的实体
@Entity
@Table(name = "ASSET_GROUPS")
@XmlRootElement
@NamedQueries({ @NamedQuery(name = "AssetGroup.findAll", query = "SELECT a FROM AssetGroup a"),
        @NamedQuery(name = "AssetGroup.findById", query = "SELECT a FROM AssetGroup a WHERE a.id = :id"),
        @NamedQuery(name = "AssetGroup.findByName", query = "SELECT a FROM AssetGroup a WHERE a.name = :name") })
public class AssetGroup implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name = "asset_groups_id_seq_gen", sequenceName = "asset_groups_id_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "asset_groups_id_seq_gen")
    @Column(name = "ID", updatable = false)
    private Long id;

    @Size(max = 255)
    private String name;

     @ManyToMany(fetch=FetchType.EAGER)
      @JoinTable(
          name="ASSETS_ASSET_GROUPS",
          joinColumns=@JoinColumn(name="ASSET_GROUP_ID", referencedColumnName="ID"),
          inverseJoinColumns=@JoinColumn(name="ASSET_ID", referencedColumnName="ID"))
    private List<Asset> assets;
    ...

第二实体:

@Entity
@Table(name = "ASSETS")
@XmlRootElement
@NamedQueries({ @NamedQuery(name = "Asset.findAll", query = "SELECT a FROM Asset a"),
        @NamedQuery(name = "Asset.findById", query = "SELECT a FROM Asset a WHERE a.id = :id"),
        @NamedQuery(name = "Asset.findByName", query = "SELECT a FROM Asset a WHERE a.name = :name")
    })
public class Asset implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name = "assets_id_seq_gen", sequenceName = "assets_id_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "assets_id_seq_gen")
    @Column(name = "ID", updatable = false)
    private Long id;

    @Size(max = 255)
    private String name;

    @ManyToMany(fetch=FetchType.EAGER, mappedBy="assets")
    List<AssetGroup> assetGroups;

    public Asset() {
    }
    ...

我可以通过REST服务添加这些东西没问题,但是这段代码给了我一个错误:

@POST
@Override
@Consumes({"application/xml", "application/json"})
@Transactional
public void create(Asset entity) {
    L.info("Creating {}", entity);
    AssetGroup g = groupService.findAll().get(0);
    L.info("Adding to asset group {}", g);
    super.create(entity);
    L.info("Created Asset {}", entity.getId());
    g.addAsset(entity); // <---- Works if this is commented out but does not create relationship!
    L.info("Created");
}

以下是上述功能的输出:

  

11:05:29,667 INFO [auth.entities.service.AssetGroupsFacadeREST]    (默认任务-2)创建entities.AssetGroup@bbad39d

     

11:05:29,672 INFO [auth.entities.service.AssetGroupsFacadeREST](默认任务-2)已创建

     

11:05:29,703 INFO [auth.entities.service.AssetsFacadeREST]   (默认任务-3)创建entities.Asset@1be5f67a

     

11:05:29,728 INFO [auth.entities.service.AssetsFacadeREST]默认任务-3)添加到资产组实体.AssetGroup@323e7d95

     

11:05:29,728 INFO [auth.entities.service.AssetsFacadeREST](默认任务-3)创建资产1

     

11:05:29,728 INFO [auth.entities.service.AssetsFacadeREST](默认任务-3)已创建

     

11:05:29,730 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper](默认任务-3)SQL错误:0,SQLState:23503

     

11:05:29,730 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper](默认任务-3)   错误:表“assets_asset_groups”上的插入或更新违反了外键约束“fk_6bl48uhb94hsmq6knndfiq3y”详细信息:表“assets”中不存在键(asset_id)=(1)。

很明显,由于资产ID 1被持久存在,数据库失败了,所以我该如何解决这个问题呢?我已经尝试在实体管理器上执行commit(),但它不起作用。我尝试使用需要新事务的super.create(entity)注释来注释@Transactional方法,但没有任何效果。

请注意,如果我注释掉注释行,则会保存实体,但不会在链接表中创建关系。

1 个答案:

答案 0 :(得分:0)

发现问题。

在我的服务类中,我有:

@PersistenceUnit(unitName = "net.mikeski_auth_war_0.1.0-SNAPSHOTPU")
private EntityManagerFactory entityManagerFactory;

因此,getEntityManager()函数执行了entityManagerFactory.createEntityManager(),这导致服务提供的群组与提供资产的服务具有不同的EntityManager。这意味着插入到asses中的插入位于从插入到关系表的单独的事务上下文中,并且它不起作用。

如果我对所有方法调用使用相同的实体管理器,它就可以工作。