java - Hibernate 只加载列表中的一个对象

标签 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/数据源配置:

<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 到配置文件(反之亦然)
  • 合作伙伴拥有多对多服务

我想要实现的是,当我加载配置文件时,我希望加载其拥有的合作伙伴,以及同时加载合作伙伴的服务。是的,我希望它们急切加载,因为它们很少是大集合,而且在这个系统中几乎总是同时需要它们。

一个示例场景是:

  • 合作伙伴 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

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

最佳答案

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

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

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

到底发生了什么我不能说的很详细,但是我们去掉了 Quartz 的 DB 依赖,只使用命名空间来处理所有的工作。之后,问题就解决了。

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

关于java - Hibernate 只加载列表中的一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8260064/

相关文章:

java - Mongo、spring 和序列化

java - 如何遍历目录中的文件及其在 Java 中的子目录?

java - 如何使用 JsonPath 从 json 中查找给定键的值?

hibernate :外键是主键

java - JPA查询具有多对多关系的多个表

java - 如何在 REST 服务中进行分页?

java - 如何使用逻辑迭代对象列表:iterate and display each object property values in jsp?

java - 来自java的多部分文件上传发布请求

hibernate - 未设置所有命名参数 : [:int]

java - 如何映射 Springs 中的字节 :select?