EJB和JPA以及@OneToMany - 交易时间太长了?

时间:2009-12-07 06:14:52

标签: jpa ejb-3.0

我正在使用EJB和JPA,当我尝试访问PhoneNumber phoneNumbers属性中的Contact contact个对象时,实际返回数据有时需要几分钟。它只返回没有phoneNumbers,甚至不返回null,然后,经过一段时间,当我再次调用它时,它会神奇地出现。

这是我访问数据的方式:

for (Contact c : contactFacade.findAll()) {
    System.out.print(c.getName()+" "+c.getSurname()+" : ");
    for (PhoneNumber pn : c.getPhoneNumbers()) {
        System.out.print(pn.getNumber()+" ("+pn.getDescription()+"); ");
    }
}

我正在使用netbeans生成的facade会话ejb(基本的CRUD方法)。 它始终打印正确的姓名和姓氏,只有经过一段时间(不一样)才能通过立面打印出来。我猜它与交易有关。怎么解决这个问题?

这些是我的JPA实体:

接触

@Entity public class Contact implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String surname;
    @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "contact")
    private Collection<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();

PHONENUMBER

@Entity
public class PhoneNumber implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String number;
    private String description;
    @ManyToOne()
    @JoinColumn(name="CONTACT_ID")
    private Contact contact;

3 个答案:

答案 0 :(得分:0)

您是否尝试过使用

fetch = FetchType.EAGER

您的OneToMany关系?

答案 1 :(得分:0)

检查生成的SQL,并尝试在数据库上查看它们所花费的时间...当他们直接在数据库中运行时! 如果你的SQL是针对一个调整不好的数据库运行的......没有什么可以帮助。

答案 2 :(得分:0)

鉴于您的实际映射,我认为您的代码实际上正在执行N + 1个请求(1个查询加载N Contact,然后每个联系人1个查询以加载其PhoneNumber)并依赖在Contact的数量上,这可能变得非常低效。热切地加载关联可能是一个好主意(使用FETCH JOIN)。

激活生成的SQL的日志记录至少可以确认此行为并查看确切发生的情况。围绕循环添加一些日志语句也有助于查看花费的时间。如果某个地方的交易出现问题,它们也应该在日志中可见。

这实际上是我的主要观点:如果你想要改进某些东西,你需要先开始测量它。没有任何措施,你只是在黑暗中拍摄一些镜头。

  

如果无法衡量,则无法改善。 - Lord Kelvin