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
方法,但没有任何效果。
请注意,如果我注释掉注释行,则会保存实体,但不会在链接表中创建关系。
答案 0 :(得分:0)
发现问题。
在我的服务类中,我有:
@PersistenceUnit(unitName = "net.mikeski_auth_war_0.1.0-SNAPSHOTPU")
private EntityManagerFactory entityManagerFactory;
因此,getEntityManager()
函数执行了entityManagerFactory.createEntityManager()
,这导致服务提供的群组与提供资产的服务具有不同的EntityManager
。这意味着插入到asses中的插入位于从插入到关系表的单独的事务上下文中,并且它不起作用。
如果我对所有方法调用使用相同的实体管理器,它就可以工作。