0

The thing is, an user has one or more properties, so that's why is this way my entity class user

@Entity
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

        // others attributes  

    //bi-directional many-to-one association to Property
    @OneToMany(mappedBy="user", fetch=FetchType.EAGER)
    private List<Property> properties;
    ..
}

My entity property:

@Entity
public class Property implements Serializable {
  private static final long serialVersionUID = 1L;
  ..
  //bi-directional many-to-one association to User
  @ManyToOne
  @JoinColumn(name="id_user")
  private User user;
  ..
}

These entities was generated by EclipseLink.

And here are my tables, which I think are ok for what I want.

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
   ..
   PRIMARY KEY (`id`),
  UNIQUE KEY `email_UNIQUE` (`email`),
  KEY `u_id_city_to_ac_id_idx` (`id_city`),
  KEY `u_id_state_to_as_id_idx` (`id_state`),
  KEY `u_id_country_to_acy_id_idx` (`id_country`),
  CONSTRAINT `u_id_city_to_ac_id` FOREIGN KEY (`id_city`) REFERENCES `address_city` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `u_id_country_to_acy_id` FOREIGN KEY (`id_country`) REFERENCES `address_country` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `u_id_state_to_as_id` FOREIGN KEY (`id_state`) REFERENCES `address_state` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8 COMMENT='an user can be a tenant and a landlord also';

And my property table:

CREATE TABLE `property` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `id_user` int(11) unsigned NOT NULL,
   ..
    PRIMARY KEY (`id`),
  KEY `p_id_accomodation_to_pac_id_idx` (`id_accomodation`),
  KEY `p_id_room_type_to_prt_id_idx` (`id_room_type`),
  KEY `p_id_bed_type_to_pbt_id_idx` (`id_bed_type`),
  KEY `p_id_policty_cancelation_to_pc_id_idx` (`id_policy_cancelation`),
  KEY `p_id_user_to_u_id_idx` (`id_user`),
  KEY `p_id_city_to_ac_id_idx` (`id_city`),
  KEY `p_id_state_to_as_id_idx` (`id_state`),
  KEY `p_id_country_to_acy_id_idx` (`id_country`),
  CONSTRAINT `p_id_accomodation_to_pac_id` FOREIGN KEY (`id_accomodation`) REFERENCES `property_accomodation` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `p_id_bed_type_to_pbt_id` FOREIGN KEY (`id_bed_type`) REFERENCES `property_bed_type` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `p_id_city_to_ac_id` FOREIGN KEY (`id_city`) REFERENCES `address_city` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `p_id_country_to_acy_id` FOREIGN KEY (`id_country`) REFERENCES `address_country` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `p_id_policty_cancelation_to_pc_id` FOREIGN KEY (`id_policy_cancelation`) REFERENCES `policy_cancellation` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `p_id_room_type_to_prt_id` FOREIGN KEY (`id_room_type`) REFERENCES `property_room_type` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `p_id_state_to_as_id` FOREIGN KEY (`id_state`) REFERENCES `address_state` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `p_id_user_to_u_id` FOREIGN KEY (`id_user`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

I would like to fetch all properties of user in a login action for instance:

user = userEAO.find(user.getEmail());
user.getProperties(); //always empty

How can I do that ? I thought that putting which type of fetching was enought but it seems it is not.

update I change to LAZY my FetchType, look now:

//bi-directional many-to-one association to Property @OneToMany(mappedBy="user", fetch=FetchType.LAZY) private List properties;

When the user log in the system :

User u = userEAO.findByEmail(profile.getEmail());
if (u != null){
  if (u.getProperties() != null){
    u.getProperties().size();
    System.out.println(u.getProperties().size()); // now prints 1
}

James, when creating a new property to the user is this what you mean, refreshing the object property, right ? And yes, after creating this property I add it into user list properties =]

public Message create(Property property) {
        try{
            em.persist(property);
            em.flush();
            em.refresh(property);
        }catch(ConstraintViolationException cve){
            cve.printStackTrace();

        }catch (Exception e) {
            e.printStackTrace();
            // 1062 : duplicate entry
            if (e.getMessage().contains("Duplicate"))
                return new Message(-1000);
            else{
                e.printStackTrace();
                return new Message(-1);
            }
        }
        return new Message(0);
    }
Valter Silva
  • 16,446
  • 52
  • 137
  • 218
  • 1
    There's no need to add tags to your titles, there's a tag system for that. Please read http://meta.stackexchange.com/q/19190/147072 for more information. – Patrick Apr 14 '13 at 22:17
  • 2
    Try to refresh the entity, then access the collection. If that works, it means you haven't maintained both sides of your bidirectional relationships, which corrupts the cache. – Chris Apr 15 '13 at 12:11

2 Answers2

2

FetchType.EAGER means that your Property list will be retrieved at same time than the object. LAZY means that your list will be retrieved as soon as you will call getProperties().anyMethod(). On condition however that your User object is stil managed by JPA (means that it currently exist an instance of EntityManager managing your entity instance).

The interest of eager is that you will be able to access your list even if the EntityManagerhas been closed (cause your underlying transaction has been closed for example). The one of lazy that you don't execute a query and map objects in memory until they are effectively used

So in your case if the list is empty it's not related to fetch mode (you explicitly call the getProperties() as soon as you've retrieved the User) but it's because you have no data in DB or something fail in your mapping.

Gab
  • 7,869
  • 4
  • 37
  • 68
  • Actually, lazy loading will happen as soon as you call a method on the list returned by getProperties(). Just calling getProperties() won't trigger lazy-loading. – JB Nizet Apr 14 '13 at 22:00
  • @Gab, I update my post with my relations and tables, what you think could be wrong there ? – Valter Silva Apr 14 '13 at 22:15
  • 1
    @JBNizet, should I user `getProperties.get(0)` for instance, to load my `properties` then ? – Valter Silva Apr 14 '13 at 22:24
  • yes he's right i forgot. U're looking it using debugger aren't you ? getSize() can make the job too – Gab Apr 14 '13 at 22:36
  • sorry dude, I'm having some problem to debug my code http://stackoverflow.com/questions/16006027/how-use-debug-with-eclipse-glassfish-3, but I will see your approach right away. – Valter Silva Apr 15 '13 at 00:41
1

Ensure that when you persist your User object you have set is properties. When you persist a new Property ensure you set its User and add the Property to the User's properties. You need to maintain both sides of a bi-directional relationship.

You could also try executing a refresh().

James
  • 17,965
  • 11
  • 91
  • 146