2017-01-31 41 views
0

我正在使用一個外部服務,該服務在我的應用程序中發佈到端點,其中我有一個@RequestBody CalloutRequest calloutRequest,其中我將請求主體映射到CalloutRequest類。使用Spring數據在BLOB上構建JPQL JPA

作爲該CalloutRequest的一部分,是一個叫userAttributes場,看起來像這樣在我的課:

@Lob  
private HashMap<String, List<String>> userAttributes; 

我把它標註的機智@Lob因爲我沒有類,我可以映射它,由於它是相當複雜的性質。所以這個HashMap。什麼userAttributes的一個例子是這樣的,當以JSON格式:

"userAttributes": { 
    "lastName": [ 
     "Guy" 
    ], 
    "ExternalId": [ 
     "d9a59407-2bca-46aa-8641-3350fd95bcd1" 
    ], 
    "distinguishedName": [ 
     "CN=t2-contractor9,DC=company,DC=com" 
    ], 
    "employeeID": [], 
    "userName": [ 
     "[email protected]" 
    ], 
    "groupNames": [ 
     "ALL USERS", 
     "[email protected]" 
    ], 
    "firstName": [ 
     "T2-Contractor" 
    ], 
    "UserStore": [], 
    "phone": [], 
    "domain": [ 
     "company.com" 
    ], 
    "disabled": [ 
     "false" 
    ], 
    "email": [ 
     "[email protected]" 
    ] 
    } 

我的挑戰是,我想建立一個查詢特定的用戶名 - userAttributes.userName - 但考慮到這是存儲爲BLOB我的事實無法弄清楚如何 - 或者如果可能 - 編寫這樣的查詢。
現在我只是簡單地使用Spring Data JPA和它的存儲庫實現,但我想知道這是我可以通過自定義@Query還是使用querydsl來實現?

我的理解是正確的,如果我可以找出一種方法將上述HashMap映射到一個實際的類,我可以使用序列化/反序列化,並有一個CalloutRequest和這個新類之間的映射,我可以建立一個JPQL查詢會使用連接來實現我所追求的內容?

回答

0

什麼這裏利用的AttributeConverter實現:

public class YourEntity { 
    // ... 
    @ElementCollection 
    @Convert(name = "value", converter = StringListToStringConverter.class) 
    private Map<String, List<String>> userAttributes; 
} 

的簡單實現的StringListToStringConverter可能是:

public class StringListToStringConverter 
     implements AttributeConverter<List<String>, String> { 
    private static final String DELIMITER = "|"; 

    @Override 
    public String converToDatabaseColumn(List<String> attributes) { 
     if (attributes == null || attributes.isEmpty()) { 
     return null; 
     } 

     StringBuilder sb = new StringBuilder(); 
     for (Iterator<String> i = attribtues.iterator(); i.hasNext();) { 
     sb.append(i.next()); 
     if (i.hasNext()) { 
      sb.append(DELIMITER); 
     } 
     } 
     return sb.toString(); 
    } 

    @Override 
    public List<String> convertToEntityAttribute(String data) { 
     if (data == null) { 
     return new ArrayList<String>(); 
     } 

     List<String> values = Arrays.asList(StringHelper.split(DELIMITER, data));   
     return new ArrayList<String>(values); 
    } 
} 

你顯然必須處理的情況下輸入流中包含的您DELIMITER值排序,但它可能取決於您的使用情況。

我相信,那麼你可以使用HQL來寫你的查詢,如:

SELECT e FROM YourEntity e JOIN e.userAttributes a 
WHERE VALUE(a) = :mapValue 
+0

這似乎工作得很好!我能夠用'@ ElementCollection'和'@ Convert'實現實體。 但是我無法讓查詢工作,因爲我沒有完全理解'StringListToStringConverter'實際上做了什麼。 我以爲我可以只是傳遞一個字符串,即用戶名到查詢方法,但失敗與「參數值不符合預期的類型[java.util。列表] - 我需要提供什麼,以便轉換器可以理解我的方法? –

+0

我道歉我沒有測試這個,所以也許你可能需要調整查詢爲'WHERE VALUE(a)IN(:mapValues) '並提供名爲參數的列表''? – Naros

+0

這給了我一個: 'java.lang.ClassCastException:java.lang.String不能從'convertToDatabaseColumn'方法轉換爲java.util.List'。 我'@ Query'標註的方法看起來像這樣在我的倉庫: 'CalloutRequest findWhereUser(@Param( 「username」 的)名單用戶名);' –

0

如果您正在使用Hibernate作爲JPA實現和PostgreSQL爲DB看看到hibernate-native-json項目:

您可以序列化一個類或一個Map(在任何情況下,一個更動態的字段是必要的)。

@Entity 
public class MyClass { 

    @Type(type = "com.marvinformatics.hibernate.json.JsonListUserType") 
    @Target(Label.class) 
    private List<Label> labels = new ArrayList<Label>(); 

    @Type(type = "com.marvinformatics.hibernate.json.JsonUserType") 
    private Map<String, String> extra; 

} 

這允許HQL這樣的查詢:

​​

祝你好運!

+0

不幸的是我使用的是基於H2文件的數據庫(小項目),但我一定會記住未來的項目!謝謝。 –