Понимание разницы между отложенной и активной загрузкой является важным аспектом для оптимального запроса таблиц базы данных, участвующих в отношениях один-к-одному, один-ко-многим или многие-ко-многим. В этом посте я буду использовать 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