我在OneToMany关系中有两个实体:
父实体:
@Entity
@Table(name = "PIANOTAGLIE")
public class PianoTaglia {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String pianoTaglia;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "pianoTaglia", cascade = CascadeType.ALL)
private List<Taglia> taglie;
public PianoTaglia() {
}
[...] Getter/Setter [...]
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PianoTaglia other = (PianoTaglia) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
和儿童实体:
@Entity
@Table(name = "TAGLIE")
public class Taglia {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 10, unique = true)
private String taglia;
@ManyToOne
private PianoTaglia pianoTaglia;
public Taglia() {
}
[...] Getter/Setter [...]
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Taglia other = (Taglia) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
为了管理我的实体,我使用这个通用Dao:
public abstract class JpaDAO<E> {
protected Class<E> entityClass;
@PersistenceContext(unitName = "PrudiPU")
protected EntityManager em;
@SuppressWarnings("unchecked")
public JpaDAO() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
this.entityClass = (Class<E>) genericSuperclass.getActualTypeArguments()[0];
}
public List<E> findAll() {
TypedQuery<E> q = em.createQuery("SELECT h FROM " + entityClass.getName() + " h", entityClass);
return q.getResultList();
}
public void persist(E entity) {
em.persist(entity);
}
public E getReference(Long id) {
return em.getReference(entityClass, id);
}
}
专门为每个班级(这是PianoTagliaDao,但TagliaDao是相同的)
@Repository
public class PianoTaglieDao extends JpaDAO<PianoTaglia> {
}
当我创建PianoTaglia时,我使用生成的ID保持对对象的引用...所以我可以浏览我的应用程序,并且可以随时创建Taglia。当我创建一个Taglia时,我会以这种方式使用对PianoTaglia的引用,这是前所未有的:
PianoTaglia pt = getPreviuslyCreatedPianoTaglia(); //this is an example
Taglia tg = new Taglia();
tg.setTaglia("XXL");
tg.setPianoTaglia(pt);
pt.getTaglie().add(tg);
taglieDao.persist(tg);
taglieDao.flush(); //i need to flush for keep generated ID
[...]
如果我检查表格进入DB就可以了!所有的桌子都很好!但是,如果我试图让所有PianoTaglia获得taglie集合总是空的:
List<PianoTaglia> pianoTagle = pianoTagliaDao.findAll();
for(PianoTaglia pt : pianoTaglie) {
assert pt.getTaglie().isEmpty();
}
经过测试我找到了解决方案:当我创建taglia时,我必须保留PianoTaglie的新参考:
PianoTaglia old = getPreviuslyCreatedPianoTaglia();
PianoTaglia pt = pianoTaglieDao.getReference(old.getId()); //getReference call the namesake method in the EntityManager
Taglia tg = new Taglia();
tg.setTaglia("XXL");
tg.setPianoTaglia(pt);
pt.getTaglie().add(tg);
taglieDao.persist(tg);
taglieDao.flush(); //i need to flush for keep generated ID
[...]
通过这种方式,当我保留PianoTaglia对象时,taglie集合很好地填充..
我的问题是:为什么JPA有这种行为?
答案 0 :(得分:3)
看起来你正在存储以前创建的PianoTaglia,并在它的上下文关闭后保持良好状态,因此它被认为不受持久性单元管理。未跟踪非托管实体,因此所做的任何更改都不会反映在数据库中。这意味着pt.getTaglie()。add(tg);代码不是在entityManager知道的事情上完成的。
通过使用getReference或find api,您正在检索实体的托管实例,以便EntityManager跟踪对其所做的任何更改。你也可以替换getReference和pianoTaglieDao.persist(tg);使用pianoTaglieDao.merge(旧)调用,将旧PianoTaglia所做的更改合并到持久性单元中。尽管使用getReference或查找而不是缓存非托管实体以帮助减少过时数据的覆盖可能更好。您的缓存对象可能无法反映所做的最新更改,然后可能会被合并调用覆盖,并且为了提高性能,它将允许您稍后将应用程序扩展到多个线程和服务器,而无需进行大幅更改。
答案 1 :(得分:0)
嗨我不确定你在db中有哪些字段但是尝试添加
@JoinColumn("user_id")
代表下一行
@ManyToOne
private PianoTaglia pianoTaglia;
结果将是
@ManyToOne
@JoinColumn("pianoTagliaId")
private PianoTaglia pianoTaglia;