2016-09-27 60 views
1

我使用jOOQ 3.8.4和Postgres 9.5。 我有一個複雜的模式。其實,當我做一個簡單的選擇,如:jOOQ和StackOverflowException從選擇中提取時

create.selectFrom(ARTICLE_VIEW) 
      .orderBy(ARTICLE_VIEW.AV_CREATION_DATE 
        .desc()).limit(4).fetch(); 

我得到:

java.lang.StackOverflowError 
    org.jooq.Converters$1.<init>(Converters.java:67) 
    org.jooq.Converters.identity(Converters.java:67) 
    org.jooq.impl.DefaultBinding.pgFromString(DefaultBinding.java:2041) 
    org.jooq.impl.DefaultBinding.pgFromString(DefaultBinding.java:2130) 
    org.jooq.impl.DefaultBinding.pgFromString(DefaultBinding.java:2041) 
    org.jooq.impl.DefaultBinding.pgFromString(DefaultBinding.java:2130) 
    org.jooq.impl.DefaultBinding.pgFromString(DefaultBinding.java:2041) 

多(有趣,這是我第一次StackOverflowException)!

我激活了DEBUG記錄模式,我複製了選擇並在PGAdmin中執行它。有用。 JOOQ應該有些問題,但我不知道如何提供有用的信息。發佈我使用的模式將是瘋狂的,它需要幾十個表格。有關如何進行的任何提示?


UPDATE

這裏如下記錄類

/** 
* This class is generated by jOOQ 
*/ 
package com.model.jooq.shop.tables.records; 


import com.google.gson.JsonElement; 

import com.model.jooq.shop.enums.BrandCountry; 
import com.model.jooq.shop.enums.Color; 
import com.model.jooq.shop.enums.Discount; 
import com.model.jooq.shop.enums.Season; 
import com.model.jooq.shop.tables.ArticleView; 
import com.model.jooq.shop.udt.records.ArticleSimpleTypeRecord; 
import com.model.jooq.shop.udt.records.CategoryTypeRecord; 
import com.model.jooq.shop.udt.records.LocalizedMoneyRecord; 
import com.model.jooq.shop.udt.records.SameModelArticleTypeRecord; 

import java.io.Serializable; 
import java.sql.Timestamp; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Table; 
import javax.validation.constraints.Size; 

import org.jooq.impl.TableRecordImpl; 


/** 
* This class is generated by jOOQ. 
*/ 
@SuppressWarnings({ "all", "unchecked", "rawtypes" }) 
@Entity 
@Table(name = "article_view", schema = "shop") 
public class ArticleViewRecord extends TableRecordImpl<ArticleViewRecord> implements Serializable, Cloneable { 

    private static final long serialVersionUID = -1404712730; 

    /** 
    * Setter for <code>shop.article_view.av_article_id</code>. 
    */ 
    public ArticleViewRecord setArticleId(Long value) { 
     set(0, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_id</code>. 
    */ 
    @Column(name = "av_article_id", precision = 64) 
    public Long getArticleId() { 
     return (Long) get(0); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_model_id</code>. 
    */ 
    public ArticleViewRecord setArticleModelId(Long value) { 
     set(1, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_model_id</code>. 
    */ 
    @Column(name = "av_article_model_id", precision = 64) 
    public Long getArticleModelId() { 
     return (Long) get(1); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_name</code>. 
    */ 
    public ArticleViewRecord setArticleName(String value) { 
     set(2, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_name</code>. 
    */ 
    @Column(name = "av_article_name", length = 25) 
    @Size(max = 25) 
    public String getArticleName() { 
     return (String) get(2); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_name_for_url</code>. 
    */ 
    public ArticleViewRecord setArticleNameForUrl(String value) { 
     set(3, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_name_for_url</code>. 
    */ 
    @Column(name = "av_article_name_for_url", length = 25) 
    @Size(max = 25) 
    public String getArticleNameForUrl() { 
     return (String) get(3); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_season</code>. 
    */ 
    public ArticleViewRecord setArticleSeason(Season value) { 
     set(4, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_season</code>. 
    */ 
    @Column(name = "av_article_season") 
    public Season getArticleSeason() { 
     return (Season) get(4); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_year</code>. 
    */ 
    public ArticleViewRecord setArticleYear(Short value) { 
     set(5, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_year</code>. 
    */ 
    @Column(name = "av_article_year", precision = 16) 
    public Short getArticleYear() { 
     return (Short) get(5); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_standard_size_designation</code>. 
    */ 
    public ArticleViewRecord setArticleStandardSizeDesignation(Boolean value) { 
     set(6, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_standard_size_designation</code>. 
    */ 
    @Column(name = "av_article_standard_size_designation") 
    public Boolean getArticleStandardSizeDesignation() { 
     return (Boolean) get(6); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_ean13</code>. 
    */ 
    public ArticleViewRecord setArticleEan13(String value) { 
     set(7, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_ean13</code>. 
    */ 
    @Column(name = "av_article_ean13", length = 13) 
    @Size(max = 13) 
    public String getArticleEan13() { 
     return (String) get(7); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_config_sku</code>. 
    */ 
    public ArticleViewRecord setArticleConfigSku(String value) { 
     set(8, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_config_sku</code>. 
    */ 
    @Column(name = "av_article_config_sku", length = 12) 
    @Size(max = 12) 
    public String getArticleConfigSku() { 
     return (String) get(8); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_features</code>. 
    */ 
    public ArticleViewRecord setArticleFeatures(JsonElement value) { 
     set(9, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_features</code>. 
    */ 
    @Column(name = "av_article_features") 
    public JsonElement getArticleFeatures() { 
     return (JsonElement) get(9); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_color</code>. 
    */ 
    public ArticleViewRecord setArticleColor(Color value) { 
     set(10, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_color</code>. 
    */ 
    @Column(name = "av_article_color") 
    public Color getArticleColor() { 
     return (Color) get(10); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_color2</code>. 
    */ 
    public ArticleViewRecord setArticleColor2(Color value) { 
     set(11, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_color2</code>. 
    */ 
    @Column(name = "av_article_color2") 
    public Color getArticleColor2() { 
     return (Color) get(11); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_color3</code>. 
    */ 
    public ArticleViewRecord setArticleColor3(Color value) { 
     set(12, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_color3</code>. 
    */ 
    @Column(name = "av_article_color3") 
    public Color getArticleColor3() { 
     return (Color) get(12); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_color_detail</code>. 
    */ 
    public ArticleViewRecord setArticleColorDetail(JsonElement value) { 
     set(13, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_color_detail</code>. 
    */ 
    @Column(name = "av_article_color_detail") 
    public JsonElement getArticleColorDetail() { 
     return (JsonElement) get(13); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_paid_price</code>. 
    */ 
    public ArticleViewRecord setArticlePaidPrice(LocalizedMoneyRecord[] value) { 
     set(14, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_paid_price</code>. 
    */ 
    @Column(name = "av_article_paid_price") 
    public LocalizedMoneyRecord[] getArticlePaidPrice() { 
     return (LocalizedMoneyRecord[]) get(14); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_price</code>. 
    */ 
    public ArticleViewRecord setArticlePrice(LocalizedMoneyRecord[] value) { 
     set(15, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_price</code>. 
    */ 
    @Column(name = "av_article_price") 
    public LocalizedMoneyRecord[] getArticlePrice() { 
     return (LocalizedMoneyRecord[]) get(15); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_image_filenames</code>. 
    */ 
    public ArticleViewRecord setArticleImageFilenames(String[] value) { 
     set(16, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_image_filenames</code>. 
    */ 
    @Column(name = "av_article_image_filenames") 
    public String[] getArticleImageFilenames() { 
     return (String[]) get(16); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_active_from</code>. 
    */ 
    public ArticleViewRecord setArticleActiveFrom(Timestamp value) { 
     set(17, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_active_from</code>. 
    */ 
    @Column(name = "av_article_active_from") 
    public Timestamp getArticleActiveFrom() { 
     return (Timestamp) get(17); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_article_discount</code>. 
    */ 
    public ArticleViewRecord setArticleDiscount(Discount value) { 
     set(18, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_article_discount</code>. 
    */ 
    @Column(name = "av_article_discount") 
    public Discount getArticleDiscount() { 
     return (Discount) get(18); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_brand_id</code>. 
    */ 
    public ArticleViewRecord setBrandId(Short value) { 
     set(19, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_brand_id</code>. 
    */ 
    @Column(name = "av_brand_id", precision = 16) 
    public Short getBrandId() { 
     return (Short) get(19); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_brand_name</code>. 
    */ 
    public ArticleViewRecord setBrandName(String value) { 
     set(20, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_brand_name</code>. 
    */ 
    @Column(name = "av_brand_name", length = 25) 
    @Size(max = 25) 
    public String getBrandName() { 
     return (String) get(20); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_brand_name_for_url</code>. 
    */ 
    public ArticleViewRecord setBrandNameForUrl(String value) { 
     set(21, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_brand_name_for_url</code>. 
    */ 
    @Column(name = "av_brand_name_for_url", length = 25) 
    @Size(max = 25) 
    public String getBrandNameForUrl() { 
     return (String) get(21); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_brand_country</code>. 
    */ 
    public ArticleViewRecord setBrandCountry(BrandCountry value) { 
     set(22, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_brand_country</code>. 
    */ 
    @Column(name = "av_brand_country") 
    public BrandCountry getBrandCountry() { 
     return (BrandCountry) get(22); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_brand_logo_url</code>. 
    */ 
    public ArticleViewRecord setBrandLogoUrl(String value) { 
     set(23, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_brand_logo_url</code>. 
    */ 
    @Column(name = "av_brand_logo_url", length = 250) 
    @Size(max = 250) 
    public String getBrandLogoUrl() { 
     return (String) get(23); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_brand_facts</code>. 
    */ 
    public ArticleViewRecord setBrandFacts(JsonElement value) { 
     set(24, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_brand_facts</code>. 
    */ 
    @Column(name = "av_brand_facts") 
    public JsonElement getBrandFacts() { 
     return (JsonElement) get(24); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_commodity_group_id</code>. 
    */ 
    public ArticleViewRecord setCommodityGroupId(Long value) { 
     set(25, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_commodity_group_id</code>. 
    */ 
    @Column(name = "av_commodity_group_id", precision = 64) 
    public Long getCommodityGroupId() { 
     return (Long) get(25); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_commodity_group_name</code>. 
    */ 
    public ArticleViewRecord setCommodityGroupName(String value) { 
     set(26, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_commodity_group_name</code>. 
    */ 
    @Column(name = "av_commodity_group_name", length = 25) 
    @Size(max = 25) 
    public String getCommodityGroupName() { 
     return (String) get(26); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_commodity_group_name_for_url</code>. 
    */ 
    public ArticleViewRecord setCommodityGroupNameForUrl(String value) { 
     set(27, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_commodity_group_name_for_url</code>. 
    */ 
    @Column(name = "av_commodity_group_name_for_url", length = 25) 
    @Size(max = 25) 
    public String getCommodityGroupNameForUrl() { 
     return (String) get(27); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_categories</code>. 
    */ 
    public ArticleViewRecord setCategories(CategoryTypeRecord[] value) { 
     set(28, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_categories</code>. 
    */ 
    @Column(name = "av_categories") 
    public CategoryTypeRecord[] getCategories() { 
     return (CategoryTypeRecord[]) get(28); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_sizes</code>. 
    */ 
    public ArticleViewRecord setSizes(ArticleSimpleTypeRecord[] value) { 
     set(29, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_sizes</code>. 
    */ 
    @Column(name = "av_sizes") 
    public ArticleSimpleTypeRecord[] getSizes() { 
     return (ArticleSimpleTypeRecord[]) get(29); 
    } 

    /** 
    * Setter for <code>shop.article_view.av_all_model_colors</code>. 
    */ 
    public ArticleViewRecord setAllModelColors(SameModelArticleTypeRecord[] value) { 
     set(30, value); 
     return this; 
    } 

    /** 
    * Getter for <code>shop.article_view.av_all_model_colors</code>. 
    */ 
    @Column(name = "av_all_model_colors") 
    public SameModelArticleTypeRecord[] getAllModelColors() { 
     return (SameModelArticleTypeRecord[]) get(30); 
    } 

    // ------------------------------------------------------------------------- 
    // Constructors 
    // ------------------------------------------------------------------------- 

    /** 
    * Create a detached ArticleViewRecord 
    */ 
    public ArticleViewRecord() { 
     super(ArticleView.ACTIVE_ARTICLE_VIEW); 
    } 

    /** 
    * Create a detached, initialised ArticleViewRecord 
    */ 
    public ArticleViewRecord(Long article_id, Long article_model_id, String article_name, String article_name_for_url, Season article_season, Short article_year, Boolean article_standard_size_designation, String article_ean13, String article_config_sku, JsonElement article_features, Color article_color, Color article_color2, Color article_color3, JsonElement article_color_detail, LocalizedMoneyRecord[] article_paid_price, LocalizedMoneyRecord[] article_price, String[] article_image_filenames, Timestamp article_active_from, Discount article_discount, Short brand_id, String brand_name, String brand_name_for_url, BrandCountry brand_country, String brand_logo_url, JsonElement brand_facts, Long commodity_group_id, String commodity_group_name, String commodity_group_name_for_url, CategoryTypeRecord[] categories, ArticleSimpleTypeRecord[] sizes, SameModelArticleTypeRecord[] all_model_colors) { 
     super(ArticleView.ACTIVE_ARTICLE_VIEW); 

     set(0, article_id); 
     set(1, article_model_id); 
     set(2, article_name); 
     set(3, article_name_for_url); 
     set(4, article_season); 
     set(5, article_year); 
     set(6, article_standard_size_designation); 
     set(7, article_ean13); 
     set(8, article_config_sku); 
     set(9, article_features); 
     set(10, article_color); 
     set(11, article_color2); 
     set(12, article_color3); 
     set(13, article_color_detail); 
     set(14, article_paid_price); 
     set(15, article_price); 
     set(16, article_image_filenames); 
     set(17, article_active_from); 
     set(18, article_discount); 
     set(19, brand_id); 
     set(20, brand_name); 
     set(21, brand_name_for_url); 
     set(22, brand_country); 
     set(23, brand_logo_url); 
     set(24, brand_facts); 
     set(25, commodity_group_id); 
     set(26, commodity_group_name); 
     set(27, commodity_group_name_for_url); 
     set(28, categories); 
     set(29, sizes); 
     set(30, all_model_colors); 
    } 
} 

問題

我調試從Andrew Rueckert鏈接以下的可能來源,但它似乎是問題在於jOOQ。它不能正確處理類型內的類型。

該視圖包含一個PostgreSQL類型的ArticleSimpleTypeRecord。它內部有一個類型。 在DefaultBinding類中執行的步驟是:

  1. 方法pgFromString被稱爲與用於ArticleSimpleTypeRecord缺省轉換器。這意味着調用以下指令:

    else if(Record.class.isAssignableFrom(type)){ return(T)pgNewRecord(type,null,string); }

  2. 方法pgNewRecord嘗試通過調用下面的方法來創建從給定對象的記錄:

    public Record operate(Record record) { 
         List<String> values = PostgresUtils.toPGObject(object.toString()); 
    
         Row row = record.fieldsRow(); 
         for (int i = 0; i < row.size(); i++) { 
          pgSetValue(record, row.field(i), values.get(i)); 
         } 
         return record; 
    } 
    

    其中將設置值到使用該方法pgSetValue並從object的值記錄。

  3. 當涉及到設置爲json值jOOQ調用它調用使用轉換器,用於該領域的方法pgFromString方法pgSetValue(Record record, Field<T> field, String value)(即the PostgresJSONGsonBinding JSON converter I found on jOOQ website)的值。問題出現在方法pgFromString中。

  4. 裏面pgFromStringClass<T> type = converter.toType()返回com.google.gson.JsonElement行了,這是沒有任何缺省值綁定如此這般路線:

    else { 
        Converter<Object, T> c = (Converter<Object, T>) converter; 
        return c.from(pgFromString(c.fromType(), string)); 
    } 
    

    這裏談到的問題,因爲JSON轉換器應該值轉換成json從pgFromString(c.fromType(), string)返回的對象開始,但由於c.fromType()返回Object並且沒有默認綁定,因此對象在jOOQ中再次返回默認情況,並且一次又一次,並且我們有StackOverflowException

我看了一眼這個班的變化,似乎現在的主人已經解決了這個問題。現在有:

else if (type == Object.class) { 
     return (T) string; 
    } 

然後,我必須等待下一個jOOQ次要版本。我希望很快就會到來。

+1

你如何生成你的Record類? (發佈'ArticleViewRecord'可能會有所幫助。)它看起來像是'ARTICLE_VIEW'中的一個類型,它試圖將字符串反序列化爲非標準類型,並且陷入了無限循環。 https://github.com/jOOQ/jOOQ/blob/version-3.8.4/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java#L2130 –

+0

@AndrewRueckert記錄類已發佈。所以,我也懷疑是一樣的。視圖很好,選擇也。我知道將一些json替換爲PostgreSQL類型,這應該是問題。我只是想知道如何調試。堆棧跟蹤沒有幫助。 –

+0

我編譯版本3.9.0-SNAPSHOT **不幸的是它有另一個bug **:沒有StackOverflowException,但它將內部類型的所有值設置爲null,即使它們不是 –

回答

-1

你註冊了JsonElement的自定義綁定嗎?我們使用GSON類型爲好,而不得不做到以下幾點:

的pom.xml(略)

<plugin> 
    <groupId>org.jooq</groupId> 
    <artifactId>jooq-codegen-maven</artifactId> 
    <version>${jooq.version}</version> 

    <configuration> 
     <generator> 
      <database> 
       <forcedTypes> 
        <forcedType> 
         <name>GsonJson</name> 
         <userType>com.google.gson.JsonElement</userType> 
         <binding>com.mycompany.dao.bindings.GsonJsonBinding</binding> 
         <types>json</types> 
        </forcedType> 
       </forcedTypes> 
      </database> 
     </generator> 
    </configuration> 
</plugin> 

GsonJsonBinding.java

public class GsonJsonBinding extends GenericStringlikeBinding<JsonElement> { 
    public GsonJsonBinding() { 
     super("json", new JsonConverter()); 
    } 
} 

JsonConverter.java

public class JsonConverter implements Converter<Object, JsonElement> { 
    private static final Gson gson = new Gson(); 

    @Override 
    public JsonElement from(Object t) { 
     return t == null ? null : gson.fromJson("" + t, JsonElement.class); 
    } 

    @Override 
    public Object to(JsonElement u) { 
     return u == null || u == JsonNull.INSTANCE ? null : gson.toJson(u); 
    } 

    @Override 
    public Class<Object> fromType() { 
     return Object.class; 
    } 

    @Override 
    public Class<JsonElement> toType() { 
     return JsonElement.class; 
    } 
} 
+0

請閱讀更新的答案。 –