2
\$\begingroup\$

I am learning ORM using Hibernate by creating a movie rental application. Currently, I have the following three entities for persistence:

  • User
  • Movie
  • Rental (composite element for many-to-many mapping between above two)

Now, to handle the cart updates, I have the following code in a session scoped bean:

@ManagedBean
@SessionScoped
public class UserManager extends BaseBean implements Serializable
{
   ....

   private Map<Integer, Movie> cart;

   ....

   public void updateCart(Movie selectedMovie)
   {
      if (!isLoggedIn()) {
         return;
      }

      int id = selectedMovie.getMovieID();

      if (cart.containsKey(id)) {
         cart.remove(id);
      }
      else {
         cart.put(id, selectedMovie);
      }
   }
}

Now for user's purchase scenario, I need to keep track of the number of rentals per movie. So, I thought of adding that property to the Rental entity and use it as a value for the map. But, this class itself contains Movie as a property for the mapping as below:

<set name="rentals" cascade="all" lazy="true" table="USER_MOVIES">
      <key column="userRegistrationID" not-null="true"/>
      <composite-element class="Rental">
         <property name="bookingDate" column="bookingDate" type="date"/>
         <many-to-one name="movie" column="bookedMovieID" class="Movie" not-null="true"/>
      </composite-element>
</set>

So, while adding to / removing from cart, I will have to create / destroy an instance of the Rental class, which would be a bad idea. So I am thinking that I should restructure my entities.

Am I right in assuming the above? Is there a better approach for the above?

I am using the following:

  • JSF 2.1 + PrimeFaces
  • Hibernate 4.3
  • MySQL
\$\endgroup\$
  • 1
    \$\begingroup\$ "I need to keep track of the number of rentals per movie." And why is that? How you should store that number depends wholly on why you need it. E.g. if you need it for some monthly report you may not need to store it at all. \$\endgroup\$ – abuzittin gillifirca Apr 2 '13 at 6:47
3
\$\begingroup\$

You are not correct in assuming the above... If you want to count the number of rentals for one Movie you can do the following (given you are not removing records from your database):

@NamedQueries{
   @NamedQuery(name="Movie.getRentalCount", 
       query="SELECT COUNT FROM Rentals r WHERE r.bookMovieId = :movieId")
}
@Entity
class Movie{

   @Transient
   public static final String getRentalCount = "uniqueQueryNameForMovie";

   // ... 
}

This allows you to do the following in your purchase process:

@Inject
EntityManager entityManager;

public Long getRentalCountForMovieId(long movieId){
    TypedQuery<Long> q = entityManager.createNamedQuery(Movie.getRentalCount, Long);
    q.setParameter("movieId", movieId);
    return q.getSingleResult();
}

You'd need to use the wrapper class, as TypedQuery only accepts Objects as type.

Also it should be unneccesary to create Rental instances while changing the contents of your cart. They should only be created when you check the cart out in the end, because before that there is no need for a Rental instance...

If you decided to destroy the instances of Rental on return of the Movie: You should keep a record of older Rentals for historization and usability reasons.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.