2015-04-29 12 views
8

JDBI có hỗ trợ ràng buộc các loại enum thông qua chú thích không?@Bind có thể được sử dụng với enums và các loại tùy ý khác bằng JDBI không?

Ví dụ, giả sử một DAO trong đó có một phương pháp:

@SqlQuery("select count(*) from answer a where a.foo = :foo") 
Long someSqlQuery(@Bind("foo") Foo foo); 

Và, foo bằng Foo.BAR, tôi có thể mong đợi một truy vấn:

select count(*) from answer a where a.foo = 'BAR' 

Nếu vậy, được toString() sử dụng để xác định những gì được thay thế?

Hơn nữa, JDBI có cho phép sử dụng @Bind với bất kỳ loại nào mở rộng Object không? Và một lần nữa, nếu vậy, có phải là toString() được sử dụng không?

+0

Theo nhận xét trên, trải nghiệm của tôi sử dụng 2.5.1 là 'Enum' hoạt động theo cách tôi mô tả ở trên. Điều đó nói rằng, tôi cũng đã nhìn thấy một số hành vi kỳ lạ, xung quanh điều này, có thể do xung đột các phiên bản JDBI tại địa phương. Tôi đã hy vọng ai đó có thể chỉ cho tôi tài liệu liên quan đến tính năng này (tôi chỉ xem tài liệu thể hiện 'Chuỗi', kiểu nguyên thủy và' Ngày') và chỉ thị phiên bản được phép sử dụng '@ Bind' với' enum'. – vpiTriumph

Trả lời

9

Theo source codeEnum.name() được sử dụng, không toString()

Nếu một đối tượng được ràng buộc, jdbi sử dụng setObject(Object object) của trình điều khiển JDBC bạn đang sử dụng. Theo kinh nghiệm của tôi với PostgreSQL chẳng hạn, nó liên kết thành công Map s đến hstore và các mảng tới postgreSQL array vì đó là điều mà trình điều khiển JDBC của PostgreSQL thực hiện.

Nếu bạn muốn xử lý một loại đối tượng cụ thể theo cách cụ thể, bạn có thể triển khai ArgumentFactory s (có vẻ như không có tài liệu nào, nhưng ví dụ ở đây là Stack Overflow) hoặc BinderFactory s bây giờ.)

+0

Ghi chú nhanh: Bạn sẽ cần JDBI 2.56 hoặc mới hơn để liên kết thành công Enums. Mãi đến thời điểm này, 'EnumArgument' đã được thêm vào như một kiểu mặc định' Argument'. Vì vậy, trước đó bạn sẽ cần phải tạo ra các chức năng chính mình đang tạo ra một 'EnumArgument' và một' EnumArgumentFactory'. – vpiTriumph

+0

Ah vâng. Trên thực tế, trước đó tôi đã có rất nhiều 'getEnumName()' hack để có được xung quanh nó mà tôi đã gỡ bỏ sau này. – Natan

0

Để giải quyết câu hỏi "loại tùy ý", bạn có thể triển khai BinderFactory để liên kết với bất kỳ thứ gì bạn muốn.

@BindingAnnotation(UserBinder.UserBinderFactory.class) 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.PARAMETER}) 
public @interface UserBinder { 
    public static class UserBinderFactory implements BinderFactory { 

     @Override 
     public Binder build(Annotation annotation) { 
      return new Binder<UserBinder, User>() { 
       @Override 
       public void bind(SQLStatement<?> q, UserBinder bind, User arg) { 
        q.bind("userId", arg.getUserId()); 
        q.bind("uuid", arg.getUuid()); 
        q.bind("openId", arg.getOpenId()); 
        q.bind("givenName", arg.getGivenName()); 
        // etc. 
       } 
      }; 
     } 
    } 
} 

Điều này hữu ích nhất nếu bạn có loại phức tạp mà bạn muốn lưu trữ theo cách cụ thể, ví dụ: dữ liệu nhị phân hoặc bộ sưu tập mà bạn muốn chuyển thành CSV hoặc chỉ được lưu trữ trong các bảng ánh xạ riêng biệt. Sau đó, bạn sử dụng chất kết dính mới lạ mắt của bạn như vậy:

@SqlUpdate(
     "INSERT INTO user (openId,givenName,uuid," + 
     // etc. 
     ") VALUES (:openId,:givenName,:uuid" + 
     // etc. 
     ")" 
) 
public abstract int createUser(
     @UserBinder User user 
); 

Bạn cũng có thể sử dụng một @BindBean chú thích, mà sẽ tự động tìm kiếm các lĩnh vực trên một đối tượng bằng tên tham số ràng buộc (ví dụ như nó có thể ánh xạ một placeholder truy vấn ":userId" đến getUserId() phương pháp).

+1

Câu trả lời hay, nhưng cung cấp một ví dụ mà không thực sự làm bất cứ điều gì vượt ra ngoài những gì mặc định 'BindBean' thực hiện là một chút khó hiểu. – Madbreaks

Các vấn đề liên quan