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