Pregunta

I am trying to get the size of attendees (a list, which is a oneToMany in class Presentation)

Planning contains a OneToMany with the corresponding presentations

Every time i try to get the size of attendees it fails to lazy load them. I tried writing a query but it says that i can't use the fetch twice. Is there any good way to get the data i need?

There are a lot of discussions on the internet about this but none of them seem to solve my problem.

I am running on the latest version of hibernate (4.1.7.Final) and am using spring Release 3.2.3

Planning repo:

public interface PlanningRepository extends JpaRepository<Planning, Long>{

    @Query("select pl from Planning pl join fetch pl.presentations p join fetch p.attendees a where pl.id = ?1")
    Planning findOneById(Long id);
}

The relation in class Presentation:

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "presentation_attendees",
     joinColumns = {@JoinColumn(name = "presentation_id")},
     inverseJoinColumns = {@JoinColumn(name = "student_id")})
private List<Student> attendees;

The relation in student:

@ManyToMany(mappedBy = "attendees")
private List<Presentation> presentationsAttending;

Where i call it in PlanningController:

Planning planning = planningRepository.findOneById(1L);                       


JSONArray pArray = new JSONArray();
JSONObject planningJSON = new JSONObject();


//List<Presentation> presentations = (List<Presentation>)presentationRepository.findByPlanning(planning.getId());

for(Presentation p : planning.getPresentations()) 
{            
    sessionFactory.openSession();
    sessionFactory.getCurrentSession().getTransaction().begin();
    //i need the size of attendees
    presentationJSON.put("subscribers", p.getAttendees().size());
    sessionFactory.getCurrentSession().getTransaction().commit();
    sessionFactory.close();
}

dispatcher-servlet.xml:

<bean id="sessionFactory"
          class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="school"/>
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
¿Fue útil?

Solución 2

I solved this by changing List<> to Set<> on the ManyToMany and OneToMany relations

Otros consejos

You need to enclose your Repository calls inside of a Service method.

Ex:-

PresentationService

@Transactional
public List<Long> getAttendeesCountForPlanning(Long planningId) {
    ... 
}

This must return the List of Presentation Attendees Count for each Planning Id. So this will be enclosed within a single transaction. For more information read this post

Strange as it seems calling a transactional method in the method does not work. For example, see

@Service       
public class MyServiceImpl implements MyService{

    @Autowired
    MyDAO myDAO;


    @Override
    @Transactional(readOnly=true)
    public MyObject method1(String param) {

        return MyObject myObject = myDAO.get(param);
    }       


    @Override
        //Won't work without the transactional annotation
    public MyObject method2() {

              return method1("bla");
    }       
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top