Hibernate只从列表中加载一个对象

时间:2011-11-24 16:28:21

标签: java hibernate spring

这就是我的所作所为:

@Repository
@Transactional(propagation = Propagation.SUPPORTS)
public class ProfileDAOHibernateImpl implements ProfileDAO {

    @Autowired
    private SessionFactory sessionFactory;

    private Session currentSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public Profile getProfile(String name) {
        return (Profile) currentSession().createCriteria(Profile.class)
            .add(Restrictions.eq("name", name)).uniqueResult();
    }
    ...
}

个人资料实体:

@Entity
@Table(name = "profiles")
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int Id;

    @Column(name = "name", unique = true)
    private String name;

    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @JoinColumn(name="partner_id", nullable = false)
    private Partner partner;
    ...
}

合作伙伴实体:

@Entity
@Table(name = "partners")
public class Partner {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @OneToMany(fetch = FetchType.LAZY, cascade={CascadeType.ALL}, mappedBy = "partner")
    @OrderBy(value = "dateCreated desc")
    private Set<Profile> profiles = new HashSet<Profile>();

    @ManyToMany(fetch = FetchType.EAGER)
    @OrderBy(value = "name asc")
    @JoinTable(name = "partner_service", 
            joinColumns = { @JoinColumn(name = "partner_id") }, 
            inverseJoinColumns = { @JoinColumn(name = "service_id") })
    private Set<Service> services = new HashSet<Service>();
    ...
}

服务实体:

@Entity
@Table(name = "services")
public class Service {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "partner_service", 
            joinColumns = { @JoinColumn(name = "service_id") }, 
            inverseJoinColumns = { @JoinColumn(name = "partner_id") })
    private Set<Partner> partners = new HashSet<Partner>();
    ...
}

以下是我的hibernate / datasource配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="poolPreparedStatements" value="true" />
    <property name="maxActive" value="20" />
    <property name="initialSize" value="2" />
    <property name="maxIdle" value="2" />
</bean>

<bean id="profileDAO" class="com.eniro.partnerapi.dao.impl.ProfileDAOHibernateImpl" />

<!-- Hibernate session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.eniro.partnerapi.model" />
    <property name="hibernateProperties">
        <props>
            <prop key="dialect">org.hibernate.dialect.MySQL5Dialect</prop>
            <prop key="hibernate.hbm2ddl.auto">verify</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.jdbc.batch_size">30</prop>
        </props>
    </property>
</bean>

<tx:annotation-driven transaction-manager="txManager" />

<bean id="txManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="dataSource" ref="dataSource" />
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
  • 合作伙伴拥有OneToMany到个人资料(反之亦然)
  • 合作伙伴拥有ManyToMany to Services

我想要实现的是,当我加载个人资料时,我希望同时加载其拥有的合作伙伴合作伙伴的服务。是的,我希望他们急切地加载,因为他们很少有很好的设置,并且他们几乎总是需要同时在这个系统中。

示例场景是:

  • 合作伙伴 A有3个个人资料
  • 合作伙伴 A有5项服务
  • 首先提取合作伙伴个人资料(profileX),同时加载合作伙伴合作伙伴的服务

这是我的问题发生的地方(在我的DAO的getProfile调用中):有时只从数据库加载第一个服务(基于id),有时加载所有5个服务。

这可能是什么原因?任何人都有经验或任何事情要我继续?

编辑 - 添加其他信息

我们正在使用:

  • Hibernate 3.6.7.Final
  • MySQL连接器5.1.16
  • Spring 3.0.5.RELEASE
  • Quartz 1.6.1
  • MySQL 5.1.x
  • Tomcat 6.33

在分布式环境中,应用程序在两个单独的服务器上运行。

1 个答案:

答案 0 :(得分:0)

好吧,我们终于找到了问题。事实证明,这不一定是Hibernates的错误。

我们有一个Quartz调度程序,它正在处理作业。一旦调度程序( org.springframework.scheduling.quartz.SchedulerFactoryBean )启动,就会出现问题。这可以。但是,我们在生产中运行了两个相同应用程序的实例,因此调度程序使用数据库在两个应用程序之间进行同步,以防止作业同时从两个实例运行。

然而,这个Quartz调度程序以他自己的方式与数据库通信(没有找到任何代码),这导致Hibernates和Quartzs连接之间发生冲突,从而给出了来自DAO的奇怪加载行为。

究竟发生了什么我不能详细说明,但是我们删除了Quartz的DB依赖关系并且只使用了命名空间来处理所有作业。在那之后,问题就消失了。

警告在分布式应用程序之间使用Hibernate / JDBC和Quartz调度的人:注意组件如何处理与数据库的连接。