JsonMappingException与spring-jpa中的对象数组

时间:2014-10-21 16:15:13

标签: java spring jpa jackson

当我尝试从我的dbms获取项目时出现错误。跟随错误

com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.pharmawizardcabinet.core.entity.cabinet.Cabinet.listaFarmaci, could not initialize proxy - no Session (through reference chain: com.pharmawizardcabinet.web.beans.ResponseCabinet["cabinet"]->com.pharmawizardcabinet.core.entity.cabinet.Cabinet["listaFarmaci"])

这是我的观点

@Entity
@Table(name = "Cabinet")
public class Cabinet implements Serializable {

    private static final long serialVersionUID = 7311927404447970875L;
    @Id
    @Column(name = "Id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long Id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "cabinet")
    private List<Farmaco> listaFarmaci;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "user")
    private User user;

    @Column(name = "timestamp")
    @Temporal(TemporalType.DATE)
    private Date setLastModified;

    public Cabinet() {
    }

    @PostPersist
    @PostUpdate
    private void setLastUpdate() {
        this.setLastModified = new Date();
    }

    public List<Farmaco> getListaFarmaci() {
        return listaFarmaci;
    }

    public void setListaFarmaci(List<Farmaco> listaFarmaci) {
        this.listaFarmaci = listaFarmaci;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Long getId() {
        return Id;
    }

    public void setId(Long id) {
        Id = id;
    }

    public Date getSetLastModified() {
        return setLastModified;
    }

    public void setSetLastModified(Date setLastModified) {
        this.setLastModified = setLastModified;
    }

}

这是项目

@Entity
@Table(name = "Farmaco")
public class Farmaco implements Serializable {

    private static final long serialVersionUID = -152536676742398255L;

    public Farmaco() {
        // TODO Auto-generated constructor stub
    }

    @Column(name = "nome_farmaco")
    private String nome;

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

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

    @Id
    @Column(name = "Id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long Id;

    @Column(name = "scadenza")
    @Temporal(TemporalType.DATE)
    private Date scadenza;

    @Enumerated(EnumType.STRING)
    @Column(name = "posologia")
    private Posologia posologia;

    @Column(name = "quantita")
    private Integer quantita;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "note")
    private Note note;

    @ManyToOne(cascade =CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "cabinet_id")
    private Cabinet cabinet;

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getCodice() {
        return codice;
    }

    public void setCodice(String codice) {
        this.codice = codice;
    }

    public String getAzienda() {
        return azienda;
    }

    public void setAzienda(String azienda) {
        this.azienda = azienda;
    }

    public Long getId() {
        return Id;
    }

    public void setId(Long id) {
        Id = id;
    }

    public Date getScadenza() {
        return scadenza;
    }

    public void setScadenza(Date scadenza) {
        this.scadenza = scadenza;
    }

    public Posologia getPosologia() {
        return posologia;
    }

    public void setPosologia(Posologia posologia) {
        this.posologia = posologia;
    }

    public Integer getQuantita() {
        return quantita;
    }

    public void setQuantita(Integer quantita) {
        this.quantita = quantita;
    }

    public Note getNote() {
        return note;
    }

    public void setNote(Note note) {
        this.note = note;
    }

    public Cabinet getCabinet() {
        return cabinet;
    }

    public void setCabinet(Cabinet cabinet) {
        this.cabinet = cabinet;
    }

}

控制器就是这个

@Component("managerCabinet")
public class ManagerCabinet {

    private static Logger logger = Logger.getLogger(ManagerCabinet.class);

    @PersistenceContext(name = "pwcabinet-jpa")
    private EntityManager entityManager;

    @Transactional
    public Cabinet getCabinetByUser(User user) {
        logger.debug("[getCabinetByUser] user: " + user.getId());
        return _getCabinetByUser(user);
    }
    private Cabinet _getCabinetByUser(User user) {
        logger.debug("[_getCabinetByUser] user: " + user.getId());
        User find = entityManager.find(User.class, user.getId());
        Query searchCabinetByUser = entityManager.createQuery("Select c from Cabinet c where c.user = :userId", Cabinet.class);
        searchCabinetByUser.setParameter("userId", find);
        Cabinet cabinetSearch = (Cabinet) searchCabinetByUser.getSingleResult();
        cabinetSearch.setUser(find);
        return cabinetSearch;
    }

}

但我仍然会收到错误。

如果我以这种方式使用注释@JsonIgnore

@JsonIgnore
public List<Farmaco> getListaFarmaci() {
    return listaFarmaci;
}

他们有效,但我在结果中需要这些信息。我怎么解决它?

1 个答案:

答案 0 :(得分:0)

当你的方法private Cabinet _getCabinetByUser(User user)返回Cabinet实例时,然后在&#39;分离的&#39;国家,即不再与持久性上下文相关联。

当项目处于分离状态时,可以更长时间地访问非急切获取的关联。

由于@OneToMany的默认提取是Lazy,然后是你的情况

@OneToMany(cascade = CascadeType.ALL, mappedBy = "cabinet")
private List<Farmaco> listaFarmaci;

一旦加载的Cabinet与持久化上下文分离,就无法再访问字段listaFarmaci。

你有各种处理方式,包括:

  1. 将该字段标记为急切地获取(不管是否需要,都不会随时获取)。
  2. 强制持久化上下文保持打开状态,直到所有处理完成,通常称为OpenSessionInView模式(或反模式),具体取决于您的观点:http://java.dzone.com/articles/open-session-view-design
  3. 确保在分离之前初始化用例所需的所有数据。有多种方法可以实现这一目标:
  4. 只需访问该系列即可。通过调用size(),但这可能不适用于所有JPA提供程序。

    在JPQL查询中指定加载Cabinet的FETCH JOIN(虽然这有副作用)。 http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Join_Fetching