JPA一對多循環參考的解決,JPA循環參考解決

來源:互聯網
上載者:User

JPA一對多循環參考的解決,JPA循環參考解決

說是解決,其實不是很完美的解決的,寫出來只是想記錄一下這個問題或者看一下有沒有哪位仁兄會的,能否知道一二。

下面說說出現問題:

問題是這樣的,當我查詢一個一對多的實體的時候,工具直接就爆了,差不多我就猜到是哪裡死迴圈了,最後等了好久,查看原因,果然是堆溢出,再然後是jsckson的錯誤。那麼必然是序列化的問題了。

這是jackson的錯誤:

at java.security.AccessController.doPrivileged(Native Method)    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)    at java.lang.ClassLoader.loadClass(ClassLoader.java:412)    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1617)    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547)    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:691)    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:656)    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)

這是循環參考的錯誤:

嚴重: Servlet.service() for servlet [springDispatcherServlet] in context with path [/Shop] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError) (through reference chain: com.web.module.index.model.entity.Account["user"]->com.web.module.index.model.entity.User["accounts"]->org.hibernate.collection.internal.PersistentSet[0]->com.web.module.index.model.entity.Account["user"]->com.web.module.index.model.entity.User["accounts"]->org.hibernate.collection.internal.PersistentSet[0]->com.web.module.index.model.entity.Account["user"]->com.web.module.index.model.entity.User["accounts"]->org.hibernate.collection.internal.PersistentSet[0]->com.web.module.index.model.entity.Account["user"]->com.web.module.index.model.entity.User["accounts"]->org.hibernate.collection.internal.PersistentSet[0]->com.web.module.index.model.entity.Account["user"]->com.web.module.index.model.entity.User["accounts"]->org.hibernate.collection.internal.PersistentSet[0]->com.web.module.index.model.entity.Account["user"]->com.web.module.index.model.entity.User["accounts"]->org.hibernate.collection.internal.PersistentSet[0]->com.web.module.index.model.entity.Account["user"]->com.web.module.index.model.entity.User["accounts"]->org.hibernate.collection.internal.PersistentSet[0]-j。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。還有很多的相同的錯誤

下面是兩個實體:

User.java:

package com.web.module.index.model.entity;import java.io.Serializable;import java.util.HashSet;import java.util.Set;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.Id;import javax.persistence.OneToMany;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlRootElement;import org.hibernate.validator.constraints.NotEmpty;import com.fasterxml.jackson.annotation.JsonIgnore;@XmlAccessorType(XmlAccessType.FIELD)@XmlRootElement(name="user")@Entitypublic class User implements Serializable{        /**     *      */    private static final long serialVersionUID = 1L;    @XmlElement    @Id    private String id;    /**     * validate適用於springmvc     */    @XmlElement    //@NotEmpty    private String name;        @JsonIgnore    @OneToMany(mappedBy="user",targetEntity=Account.class,fetch=FetchType.EAGER)    private Set<Account> accounts=new HashSet<Account>();    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }        public Set<Account> getAccounts() {        return accounts;    }    public void setAccounts(Set<Account> accounts) {        this.accounts = accounts;    }    @Override    public String toString() {        return "User [id=" + id + ", name=" + name + ", accounts=" + accounts                + "]";    }    }

Account.java:

package com.web.module.index.model.entity;import java.io.Serializable;import javax.persistence.CascadeType;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.ManyToOne;import com.fasterxml.jackson.annotation.JsonIgnore;@Entitypublic class Account implements Serializable{    /**     *      */    private static final long serialVersionUID = 1L;        @Id    private String id;        private String code;    private String password;        @JsonIgnore    @JoinColumn(name="user_id")    @ManyToOne(targetEntity=User.class,fetch=FetchType.EAGER)    private User user;    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public String getCode() {        return code;    }    public void setCode(String code) {        this.code = code;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public User getUser() {        return user;    }    public void setUser(User user) {        this.user = user;    }    @Override    public String toString() {        return "Account [id=" + id + ", code=" + code + ", password="                + password + ", user=" + user + "]";    }    }

 

後來去網上看了一下,這個問題很多人遇到。解決方案也有很多.

1.在關聯的實體上面設定@JsonIgnore,這個註解的意思是表示在序列化的時候,忽略這個屬性.但是我現在的邏輯是在頁面中必須使用到這個關聯實體中的屬性,所以就不能這麼做了,不然在頁面中是取不出這個資料的。

Uncaught TypeError: Cannot read property 'name' of undefined(1,2都會出現)

2.採用單向多對一的形式,這樣就不會出現迴圈的問題,這個確實是個方案,但是如果在一的那邊需要使用到多的這邊的話,就不好搞了。所以感覺還是不是很滿意。

3.後來想了想,既然是這樣,要不我在一的那邊使用@JsonIgnore吧。目前在頁面中沒使用。其實這個是第二個是差不多的,有點不同的是除了頁面展示的時候不能夠顯示多的那面的資料,在其他的業務中還是能夠使用的。這也是我在前面說不是很滿意的解決辦法。

4.第四種解決就是前面的3差不多,當我們使用多的一邊的時候,可以正確的顯示,但是在我們使用一的那一端的時候,我們可以使用List自己拼裝,有點像下面的代碼:

@RequestMapping(value="result/{id}",method=RequestMethod.GET)    public @ResponseBody List<?> result(@PathVariable("id") String id){        System.out.println(id);        List<Map<String,Object>> list=Lists.newArrayList();        //Map<String,Object> map=new HashMap<String,Object>();        Map<String,Object> map=null;        Random r=new Random();        DecimalFormat dfmt=new DecimalFormat("#,###.00");        for(int i=0;i<4;i++){            int price=r.nextInt(10)+1;            int number=r.nextInt(100000)+10000;            map=new HashMap<String,Object>();            map.put("tradegoods", "煤"+i);            map.put("units", "頓");            map.put("consumer", "XX物流"+id);            map.put("unitPrice", dfmt.format(price));            map.put("number", dfmt.format(number));            map.put("count", dfmt.format(price*number));            list.add(map);        }        //設定日期格式          return list;    }

這樣jackson序列化的時候,就不會出錯了,而且使用起來就不用像A.B.name這樣了,而且使用起來也更加的簡單。我們在JS裡面就可以這樣使用:

if(id!=""&&id){            $.ajax({                type: 'GET',                url: $ctx + '/example/demo/result/'+id,                dataType: 'json',                success: function(data) {                    for(var i=0;i<data.length;i++){                        data[i].num=i+1;                    }                    //alert(JSON.stringify(data));                    viewModel.result(data);                    $(".notice-hide").show();                    $(".notice-show").hide();                },                error: function(req, textStatus, errorThrown){                }            });

html:

                <tbody data-bind="foreach: result">                <tr>                    <td data-bind="text:num"></td>                    <td data-bind="text:tradegoods"></td>                    <td data-bind="text:units"></td>                    <td data-bind="text:consumer"></td>                    <td data-bind="text:unitPrice" class="format_"></td>                    <td data-bind="text:number" class="format_"></td>                    <td data-bind="text:count" class="format_"></td>                </tr>            </tbody>

這樣就完美的解決了這個問題。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.