5

Tôi đang cố gắng để tồn tại đối tượng sau đây với spring-data-mongodb phiên bản 1.1.1.RELEASE:PersistenceConstructor luận tên biến không phù hợp ví dụ biến tên

@Document 
public static class TestObject { 

    private final int m_property; 

    @PersistenceConstructor 
    public TestObject(int a_property) { 
     m_property = a_property; 
    } 

    public int property() { 
     return m_property; 
    } 

} 

tôi nhận được một MappingException khi tôi cố gắng đọc các đối tượng trở về từ cơ sở dữ liệu (xem full stacktrace bên dưới)

Quy ước đặt tên nhóm của tôi sử dụng yêu cầu tên biến đối số được đặt trước bởi a_ và tên biến mẫu được bắt đầu bằng m_. Có vẻ như spring-data-mongodb là giả định rằng tên biến đối số hàm tạo phải khớp với tên biến đối tượng.

  • Tại sao không spring-data-mongodb sử dụng đối số hàm tạo cho ánh xạ biến thể mà tôi xác định trong hàm tạo?
  • Có cách nào khác để xác định ánh xạ này sao cho spring-data-mongodb sẽ xây dựng đúng đối tượng của tôi hay là tùy chọn duy nhất của tôi để phá vỡ quy ước đặt tên?

.

Exception in thread "main" org.springframework.data.mapping.model.MappingException: No property a_property found on entity class com.recorder.TestRecorder$TestObject to bind constructor parameter to! 
    at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:90) 
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:70) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:229) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:209) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:173) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:169) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:72) 
    at org.springframework.data.mongodb.core.MongoTemplate$ReadDbObjectCallback.doWith(MongoTemplate.java:1820) 
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1542) 
    at org.springframework.data.mongodb.core.MongoTemplate.findAll(MongoTemplate.java:1064) 
    at com.recorder.TestRecorder.main(TestRecorder.java:43) 
+0

Đây thực sự là quy ước đặt tên crappy không có ý nghĩa gì. –

Trả lời

16

tl; dr

Chúng ta cần phải dựa vào tên luận constructor để phù hợp với tên trường để tìm ra các lĩnh vực tài liệu để kéo trong Nếu bạn muốn tùy chỉnh sử dụng này @Value("#root.field_name") trên đối số nhà xây dựng..

câu chuyện dài

Nếu bạn đang sử dụng một constructor với lập luận để cho mùa xuân dữ liệu nhanh chóng lớp được sử dụng constructor này chúng ta phải bàn tham số cho các nhà xây dựng theo sự thỉnh nguyện. Để tìm ra trường tài liệu nào chúng ta phải đưa vào, chúng ta cần phải kiểm tra thuộc tính phù hợp để tùy chỉnh tên trường tiềm năng. Xem ví dụ sau:

@Document 
class MyEntity { 

    @Field("foo") 
    private String myField; 

    public MyEntity(String myField) { 
    this.myField = myField; 
    } 
} 

Trong trường hợp này chúng ta cần phải ống lĩnh vực foo vào constructor và không có cách nào để tìm hiểu về vấn đề này nếu chúng ta không bằng cách nào đó có thể có được một tham chiếu đến tài sản. Nếu tên tham số hàm tạo khác nhau, chúng ta nên tìm ra giá trị trường nào thực sự nên được sử dụng làm đối số?Ví dụ bạn đã hiển thị trong câu hỏi của mình có thể là không hoạt động, vì tài liệu của bạn có chứa trường m_property và hoàn toàn không có cách nào để tìm ra bạn thực sự muốn được tiêm, ngoại trừ việc thêm cấu hình rõ ràng hơn.

Để tùy chỉnh hành vi này, bạn có thể sử dụng chú thích @Value của Spring và đưa trường tài liệu tùy chỉnh vào hàm tạo. Bản thân tài liệu có sẵn thông qua biến số #root. Vì vậy, bạn có thể dễ dàng thay đổi mẫu của tôi ở trên để:

@Document 
class MyEntity { 

    @Field("foo") 
    private String myField; 

    public MyEntity(@Value("#root.foo") String somethingDifferent) { 
    this.myField = somethingDifferent; 
    } 
} 

Tôi rất muốn khuyên bạn nên thêm tên trường tùy chỉnh để tài sản của bạn cũng như bạn không muốn để lộ ước đặt tên tài sản của mình vào cơ sở dữ liệu. Việc sử dụng pf @Value được đề cập ngắn gọn trong reference docs nhưng tôi đã tạo a ticket để cải thiện tài liệu và làm cho điều này rõ ràng hơn.

+0

Một câu hỏi tiếp theo cho bạn - nếu tôi làm những gì bạn đề xuất, có vẻ như nó hoạt động cho các đối tượng chỉ chứa các nguyên thủy, nhưng tôi nhận được một ngoại lệ bất cứ khi nào tôi cố gắng sử dụng các đối tượng chứa các đối tượng khác. Bạn có biết chuyện gì đang xảy ra ở đây không? Tôi đã liệt kê chi tiết trong [Câu hỏi 13854753] (http://stackoverflow.com/questions/13854753) –

+0

FYI - Tôi đã tạo [DATAMONGO-592] (https://jira.springsource.org/browse/DATAMONGO -592) để theo dõi vấn đề không thể sử dụng các đối tượng có chứa các đối tượng khác. Cảm ơn bạn đã giúp đỡ!! –

+0

Oh cách tôi yêu stackoverflow và những người đóng góp vào nó! Tôi có thể đã dành một vài ngày cố gắng để tìm ra những gì sai, bạn chỉ cần lưu tôi tất cả thời gian và thất vọng. Cảm ơn bạn! – TheZuck

0

Bạn có thể sử dụng một số bộ chuyển đổi tùy chỉnh (và loại bỏ @PersistenceConstructor):

// DB => Java 
package com.recorder.converters; 

public class TestObjectReadConverter implements Converter<DBObject, TestObject> 
{ 
    public TestObject convert(final DBObject source) { 
     return new TestObject((Integer) source.get("m_property")); 
    } 
} 

.

// JAVA => DB 
package com.recorder.converters; 

public class TestObjectWriteConverter implements Converter<TestObject, DBObject> 
{ 
    public DBObject convert(final TestObject source) { 
     return new BasicDBObjectBuilder("m_property", source.property()).get(); 
    } 
} 

Đừng quên để tuyên bố những người (xml config):

<mongo:mapping-converter base-package="com.recorder"> 
    <mongo:custom-converters> 
     <mongo:converter> 
      <bean class="com.recorder.converters.TestObjectReadConverter" /> 
     </mongo:converter> 
     <mongo:converter> 
      <bean class="com.recorder.converters.TestObjectWriteConverter"/> 
     </mongo:converter> 
    </mongo:custom-converters> 
</mongo:mapping-converter> 

thấy this reference

Side lưu ý: đây là một công trình xung quanh, tôi không nghĩ rằng quy ước đặt tên có nghĩa là rất chặt chẽ mà bạn cần phải làm việc xung quanh. Có lẽ đã đến lúc nhóm của bạn "suy nghĩ lại" quy ước đặt tên đó (vì lợi ích năng suất trong trường hợp đó).