2015-09-28 4 views
1

Я пытаюсь извлечь только часть модели, используя Ebean в Play! Framework, но у меня возникли проблемы, и я не нашел никаких решений.Ebean и Play! не фильтруя столбцы с .select()

У меня есть эти модели:

User:

@Entity 
@Table(name = "users") 
@JsonInclude(JsonInclude.Include.NON_NULL) 
public class User extends Model{ 
    @Id 
    private int id; 
    @NotNull 
    @Column(name = "first_name", nullable = false) 
    private String firstName; 
    @Column(name = "last_name") 
    private String lastName; 
    @NotNull 
    @Column(nullable = false) 
    private String username; 
    @NotNull 
    @Column(nullable = false) 
    private String email; 
    private String gender; 
    private String locale; 
    private Date birthday; 
    private String bio; 
    @NotNull 
    @Column(nullable = false) 
    private boolean active; 
    private String avatar; 
    @Column(name = "created_at",nullable = false) 
    private Date createdAt; 

    @OneToMany 
    private List<UserToken> userTokens; 

    // Getters and Setters omitted for brevity 
} 

UserToken:

@Entity 
@Table(name = "user_tokens") 
public class UserToken extends Model { 
    @Id 
    private int id; 
    @Column(name = "user_id") 
    private int userId; 
    private String token; 
    @Column(name = "created_at") 
    @CreatedTimestamp 
    private Date createdAt; 

    @ManyToOne 
    private User user; 

    // Getters and Setters omitted for brevity 
} 

И потом, у меня есть контроллер UserController:

public class UserController extends Controller{ 
    public static Result list(){ 
     User user = Ebean.find(User.class).select("firstName").where().idEq(1).findUnique(); 
     return Results.ok(Json.toJson(user)); 
    } 
} 

Я ожидал, что при использовании .select() он будет фильтровать поля и загружать частичный объект, но он полностью загружает его. В журналах есть больше проблем, которые я не знаю, почему это происходит.

Statements logs

Это делает 3 запросов. Сначала это то, что я хочу. И затем он заставляет забрать всю модель, а другой - UserTokens. Я не знаю, почему он выполняет эти последние два запроса, и я хотел, чтобы только первый был выполнен.

Решения Редактировать

После уже принял тот факт, что я должен был бы построить JSon как это было предложено @biesior, я нашел (из nowhere) решения!

public static Result list() throws JsonProcessingException { 
    User user = Ebean.find(User.class).select("firstName").where().idEq(1).findUnique(); 
    JsonContext jc = Ebean.createJsonContext(); 
    return Results.ok(jc.toJsonString(user)); 
} 

оказывает только поля выбранных разыскиваемые в .select() после использования JsonContext.

ответ

1

Это просто, когда вы используете select("...") всегда получает только id поле (не избежать - это требуется для отображения) + нужные поля, но если позже вы пытаетесь получить доступ поле, которое не было доступно в первом select("...") - Ebean повторяет запрос и отображает весь объект.

Другими словами, вы обращаетесь к тому месту, которое не было доступно в первом запросе, анализируйте ваш контроллер и/или шаблоны, найдите все поля и добавьте их в свой выбор (даже если они прокомментированы с обычным ! HTML комментарий в представлении)

+0

Прежде всего, спасибо за ответ. Ну, я видел, что это делал это, когда я явно вызывал 'user.getLastName()', в то время как я просто выбираю 'firstName', но в этом случае после того, как я выбираю, я просто выдаю json, поэтому я не знаю, почему он снова запрашивает. Нет никакого представления или чего-то еще, он заканчивается этим возвратом Results.ok (Json.toJson (пользователь)); '. Если этот 'Results.ok()' не делает что-то под капотом. – augustoccesar

+0

да, см. Этот ответ http://stackoverflow.com/a/14717035/1066240, может быть, это не самое удобное, в любом случае дает вам полную гибкость (как вы можете добавить любое количество внутренних классов для разных сценариев) – biesior

+0

Я вижу ..Я думал о чем-то подобном, но я этого не делал из-за одного: учитывая, что мне нужно только одно поле модели, я могу сделать один запрос чистым, чтобы получить только это поле. Но используя этот метод построения, мне пришлось бы запрашивать все поля из базы данных и затем фильтровать в Java-коде. В больших масштабах не будет более тяжелым для БД запрашивать много полей и отношений, учитывая, что мне просто нужны некоторые из них? – augustoccesar

0

в последней версии Play Framework (2.6) надлежащим образом, чтобы сделать это:

public Result list() { 
     JsonContext json = ebeanServer.json(); 

     List<MyClass> orders= ebeanServer.find(MyClass.class).select("id,property1,property2").findList(); 

     return ok(json.toJson(orders)); 
    }