Статьи

Тестирование ленивого механизма в EJB 3

Понимание разницы между отложенной и активной загрузкой является важным аспектом для оптимального запроса таблиц базы данных, участвующих в отношениях один-к-одному, один-ко-многим или многие-ко-многим. В этом посте я буду использовать EJB 3 для запроса данных из такой базы данных, используя механизм отложенной загрузки. В нашей базе данных есть две таблицы, команды, в которых хранятся несколько футбольных команд, и  игроки, в которых содержатся игроки каждой команды. В качестве отношения мы будем использовать двунаправленное отношение один ко многим, это означает, что одна команда из таблицы команд имеет одного или нескольких игроков из таблицы игроков, и каждый игрок принадлежит к одной команде.

Ниже приведен код трех наших участников, участвующих в двунаправленных отношениях «один ко многим». Во-первых, Teams.java:

. . .
@Entity
@Table(name = "teams")
@XmlRootElement
@NamedQueries({@NamedQuery(name = "Teams.findAll", query = "SELECT t FROM Teams t")})
public class Teams implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @NotNull
    @Column(name = "id")
    private Integer id;
    @Size(max = 45)
    @Column(name = "team")
    private String team;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "teams", 
fetch = FetchType.LAZY
)
    private List playerslist;
    @XmlTransient
    public List getPlayerslist() {
        return playerslist;
    }
    public void setPlayerslist(List playerslist) {
        this.playerslist = playerslist;
    }
. . .
// getters and setters
. . .

Во-вторых, Players.java:

. . .
@Entity
@Table(name = "players")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Players.findAll", query = "SELECT p FROM Players p")})
public class Players implements Serializable {
    private static final long serialVersionUID = 1L;
    @EmbeddedId
    protected PlayersPK playersPK;
    @Size(max = 45)
    @Column(name = "name")
    private String name;
    @Size(max = 45)
    @Column(name = "surname")
    private String surname;
    @Column(name = "age")
    private Integer age;
    @JoinColumn(name = "Teams_id", referencedColumnName = "id", insertable = false,
                       updatable = false)
    @ManyToOne(optional = false, 
fetch = FetchType.LAZY
)
    private Teams teams;
. . .
// getters and setters
. . .

И третий, PlayersPK.java:

. . .
@Embeddable
public class PlayersPK implements Serializable {

    @Basic(optional = false)
    @NotNull
    @Column(name = "id")
    private int id;
    @Basic(optional = false)
    @NotNull
    @Column(name = "Teams_id")
    private int teamsid;
. . .
// getters and setters
. . .

Тип загрузки отмечен с помощью
элемента
fetch, как показано выше жирным шрифтом. В этом случае,
ленивая загрузка будет получать связанные entites только по мере необходимости, в то время как
нетерпеливые погрузочные пытается установить получить все связанные entites как когда — то. Но действительно ли это работает?

В нашем bean-компоненте без состояния мы определим метод, который получит нам список
записей
команд :

. . .
@Stateless
@LocalBean
public class Calls {

    @PersistenceContext(unitName = "Ucl-one-to-many-ejbPU")
    private EntityManager manager;

    public List teamsFindAll() {
        Query query = manager.createNamedQuery("Teams.findAll", Teams.class);
        if (query.getResultList().isEmpty() == false) {
            return query.getResultList();
        }
        return null;
    }
} 
. . .

Теперь мы используем JSF для рендеринга извлеченных таблиц. Обратите внимание, что мы визуализируем только команды, а не игроков, что означает, что механизм LAZY должен выполнять свою работу, а не извлекать игроков из базы данных! Управляемый компонент JSF довольно прост:

.. .
@ManagedBean
@RequestScoped
public class UclTeams {
    @EJB
    private Calls records;
    private List teams = new ArrayList();

    public List getTeams() {
        this.teams = records.teamsFindAll();
        return teams;
    }

    public void setTeams(List teams) {
        this.teams = teams;
    }
. . .

Чтобы продемонстрировать
ленивый механизм на нашей
странице
index.xhtml, мы сначала будем иметь:

. . .
            <h1>Testing LAZY mechanism in EJB 3</h1>
            <h:form>
                <h:dataTable value="#{uclTeams.teams}" var="a"
                             styleClass="table"
                             headerClass="header"
                             rowClasses="row-one,row-two">
                    <h:column>
                        <f:facet name="header">id</f:facet>
                        #{a.id}
                    </h:column>
                    <h:column>
                        <f:facet name="header">team</f:facet>
                        #{a.team}
                    </h:column>
                    <h:column>
                        <f:facet name="header">players</f:facet>
                        #{a.playerslist}
                    </h:column> 
                </h:dataTable>
            </h:form>
. . .

При запуске в колонку игроков мы получим сообщение
«IndirectList: not instantiated» . Это потому , что
ленивы нагрузка будет гарантировать , что соответствующие записи не были retrived , пока они не просят — поэтому LAZY работает.
Добавление кода для отображения информации об игроках заставит LAZY загружать игроков запрашиваемых команд также:

. . .
                    <h:column>
                        <f:facet name="header">team</f:facet>
                        #{a.team}
                    </h:column>
                    <h:column>
                        <f:facet name="header">players</f:facet>
                        <h:dataTable value="#{a.playerslist}" var="b"
                                     styleClass="table"
                                     headerClass="header-two"
                                     rowClasses="row-one,row-two">
                            <h:column>
                                <f:facet name="header">name</f:facet>
                                #{b.name}
                            </h:column>
                            <h:column>
                                <f:facet name="header">surname</f:facet>
                                #{b.surname}
                            </h:column>
                            <h:column>
                                <f:facet name="header">age</f:facet>
                                #{b.age}
                            </h:column>
                        </h:dataTable>
                    </h:column>
. . .

И результат будет таким:
Это был простой тест для ленивого механизма! Надеюсь, вам понравится.

 

С http://e-blog-java.blogspot.com/2011/11/testing-lazy-mechanism-in-ejb-3.html