-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 
Author Message
 Post subject: Mapping table is empty
PostPosted: Thu Jul 02, 2009 8:42 pm 
Beginner
Beginner

Joined: Fri Mar 21, 2008 8:07 pm
Posts: 23
Question:

Why is person_emails empty once PopulateData.afterPropertiesSet() runs?

Database contents after PopulateData.afterPropertiesSet() runs:

Code:
mysql> select * from person_emails;
Empty set (0.00 sec)

mysql> select * from emails;
+----+---------------------+-------------+----------+----------------+
| id | created             | description | name     | value          |
+----+---------------------+-------------+----------+----------------+
|  1 | 2009-07-01 13:21:19 | NULL        | Other    | test@gmail.com |
|  2 | 2009-07-01 13:21:19 | NULL        | Work     | work@test.com  |
|  3 | 2009-07-01 13:21:19 | NULL        | Personal | test@test.com  |
|  4 | 2009-07-01 13:21:19 | NULL        | Admin    | admin@test.com |
+----+---------------------+-------------+----------+----------------+
4 rows in set (0.01 sec)

mysql> select * from persons;
+----+---------------------+-------+-------+--------+------+--------+
| id | created             | birth | first | gender | last | middle |
+----+---------------------+-------+-------+--------+------+--------+
|  1 | 2009-07-01 13:21:19 | NULL  | Test  |   NULL | User | NULL   |
|  2 | 2009-07-01 13:21:19 | NULL  | Admin |   NULL | User | NULL   |
+----+---------------------+-------+-------+--------+------+--------+
2 rows in set (0.01 sec)

mysql> select * from members;
+----+---------------------+----------+----------+--------+
| id | created             | password | username | person |
+----+---------------------+----------+----------+--------+
|  1 | 2009-07-01 13:21:19 | test     | test     |      1 |
|  2 | 2009-07-01 13:21:19 | admin    | admin    |      2 |
+----+---------------------+----------+----------+--------+
2 rows in set (0.00 sec)

mysql> show create table person_emails;
| person_emails | CREATE TABLE `person_emails` (
  `persons_id` bigint(20) NOT NULL,
  `emails_id` bigint(20) NOT NULL,
  PRIMARY KEY  (`persons_id`,`emails_id`),
  KEY `FKADA310811EAC00B6` (`persons_id`),
  KEY `FKADA31081C962EC01` (`emails_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |

mysql> desc person_emails;
+------------+------------+------+-----+---------+-------+
| Field      | Type       | Null | Key | Default | Extra |
+------------+------------+------+-----+---------+-------+
| persons_id | bigint(20) | NO   | PRI | NULL    |       |
| emails_id  | bigint(20) | NO   | PRI | NULL    |       |
+------------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)


Create members

Code:
@Repository("populateData")
@Transactional
public class PopulateData implements InitializingBean {
   
    private static final Logger log = LoggerFactory.getLogger(PopulateData.class);

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

//   @Transactional(propagation=Propagation.REQUIRES_NEW)
   public void afterPropertiesSet() throws Exception {
       log.debug("Building Member Data");

       Session sess = sessionFactory.openSession();
   
      for (int i = 0; i < MEMBERS.length; i++) {
         Member m= new Member();
         m.setUsername(MEMBERS[i][0]);
         m.setPassword(MEMBERS[i][0]);
         m.setCreated(new Date());
         
         Person p = new Person();
         p.setMember(m);
         p.setCreated(new Date());
         p.setFirst(MEMBERS[i][1]);
         p.setLast(MEMBERS[i][2]);

         m.setPerson(p);

         for (int j = 0; j < EMAILS[i].length; j++) {
            Email email = new Email();
            String data[] = EMAILS[i][j].split("[|]");
            email.setCreated(new Date());
            email.setName(data[0]);
            email.setValue(data[1]);
            p.addEmail(email);
         }
           sess.save(m);

      }
   }

    private static final String[][] MEMBERS = {
      {"test","Test","User"},
      {"admin","Admin","User"}
   };

   private static final String[][] EMAILS = {
      {"Personal|test@test.com","Work|work@test.com","Other|test@gmail.com"},
      {"Admin|admin@test.com"}
   };
}


Member.java

Code:
@Entity
@Table(name="members")
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
public class Member extends AbstractEntity {
   private static final long serialVersionUID = 1L;

    private String username;
    private String password;
    private Person person;

   public Member() {
      super();
   }

    @Basic(optional=false)
    @Column(length=100)
    @Index(name="idx_members_username")
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Basic(optional=false)
    @Column(length=255)
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "person")
//    @PrimaryKeyJoinColumn
   public Person getPerson() {
      return person;
   }
   public void setPerson(Person person) {
      this.person = person;
   }

}


Person.java

Code:
@Entity
@Table(name="persons")
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
public class Person extends AbstractEntity {
   private static final long serialVersionUID = 1L;

    private String first;
    private String last;

    private Member member;

   private Set<Email> emails = new HashSet<Email>();

   public Person() {
      super();
   }
   
    @Basic(optional=false)
    @Column(length=50)
    @Index(name="idx_person_first")
   public String getFirst() {
      return first;
   }
   public void setFirst(String first) {
      this.first = first;
   }
   
   @Basic(optional=false)
    @Column(length=50)
    @Index(name="idx_person_last")
   public String getLast() {
      return last;
   }
   public void setLast(String last) {
      this.last = last;
   }
   
    @OneToOne(mappedBy = "person")
   public Member getMember() {
      return member;
   }
   public void setMember(Member member) {
      this.member = member;
   }
   
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name="person_emails")
    @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
   public Set<Email> getEmails() {
      return this.emails;
   }
   public void setEmails(Set<Email> emails) {
      this.emails = emails;
   }
   public Email hasEmail(Email email) {
      if (this.emails.contains(email)) {
         return email;
      }
      return null;
   }
   public boolean addEmail(Email email) {
      return this.emails.add(email);
   }
   public boolean removeEmail(Email email) {
      return this.emails.remove(email);
   }

}


Email.java

Code:
@Entity
@Table(name="emails")
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
public class Email extends NamedEntity {
    private static final long serialVersionUID = 1L;

    private String value;

    public Email() {
   }

    @Basic
    @Column(length=255)
   public String getValue() {
      return value;
   }
   public void setValue(String value) {
      this.value = value;
   }

}


NamedEntity.java

Code:
@MappedSuperclass
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
public abstract class NamedEntity extends AbstractEntity {
   private static final long serialVersionUID = 1L;

   private String name;
   private String description;
   
   public NamedEntity() {
      super();
   }
   
    @Basic(optional=false)
    @Column(length=100)
    @Index(name="idx_name")
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }

   @Lob
   public String getDescription() {
      return description;
   }
   public void setDescription(String description) {
      this.description = description;
   }
}


AbstractEntity.java

Code:
@MappedSuperclass
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
public abstract class AbstractEntity implements IEntity {
   private static final long serialVersionUID = 1L;

   private Long id;
   private Date created;

   public AbstractEntity() {
      super();
   }

    @Id
    @GeneratedValue
   public Long getId() {
       return this.id;
   }
   @SuppressWarnings("unused")
   private void setId(Long id) {
       this.id = id;
   }

   @Temporal(TemporalType.TIMESTAMP)
    @Index(name="idx_entity_created")
   public Date getCreated() {
      return created;
   }
   public void setCreated(Date created) {
      this.created = created;
   }

}


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Fri Jul 03, 2009 3:29 am 
Regular
Regular

Joined: Sun Sep 30, 2007 7:51 pm
Posts: 93
What about starting and committing a transaction ?

Code:
Session sess = factory.openSession();
Transaction tx;
try {
     tx = sess.beginTransaction();
     //do some work
     ...
     tx.commit();
}
catch (Exception e) {
     if (tx!=null) tx.rollback();
     throw e;
}
finally {
     sess.close();
}


https://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Fri Jul 03, 2009 3:30 am 
Regular
Regular

Joined: Sun Sep 30, 2007 7:51 pm
Posts: 93
Aaa sorry, it's a bean.


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Fri Jul 03, 2009 3:56 am 
Beginner
Beginner

Joined: Fri Mar 21, 2008 8:07 pm
Posts: 23
pavol.zibrita wrote:
Aaa sorry, it's a bean.


Yeah, I should have been more clear that I'm using Spring beans and managed transactions.

Also, I wanted to clarify why I want the Email address to be a separate entity instead of a component within Person. I actually have several other objects as part of Person as well (Set<Phone>, Set<Address>) and am just using Set<Email> as an example of the issue.

My data model has the notion of Family groups, as in Mom, Dad, and children. Each person in a family may or may not share the same email addresses, physical addresses, and phone numbers. If the family moves, I don't want Dad to have to change the address for each member of the family. One update should change them all.

I've tried to simplify this example in the hopes it will be easier to solve.

Thanks,
Tauren


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Fri Jul 03, 2009 4:27 am 
Regular
Regular

Joined: Sun Sep 30, 2007 7:51 pm
Posts: 93
Well, than that is just maybe a stupid question from me.
Where the spring starts and commits the transaction when you are opening session in the bean? How does he gets your session object? I don't know spring at all...

The session factory is customized by spring, and on openSession the transaction is started and registred and after bean ends, the transaction is commited?


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Fri Jul 03, 2009 4:35 am 
Regular
Regular

Joined: Fri Jan 30, 2009 10:10 am
Posts: 74
Location: London
How about trying
Code:
Session sess = factory.getCurrentSession()

instead of openSession()?

It looks like Spring should be setting a session up for you - @Transactional - but you are then establishing a new session.


--
Stephen Souness


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Fri Jul 03, 2009 1:11 pm 
Beginner
Beginner

Joined: Fri Mar 21, 2008 8:07 pm
Posts: 23
It's interesting that you think it is related to the session or transaction. Does this mean that the mappings look correct to you?

I actually originally was using getCurrentSession(), but when I use it I get the following exception:

Code:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
   at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
   at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
   at com.sprtz.service.PopulateData.afterPropertiesSet(PopulateData.java:36)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
   at java.security.AccessController.doPrivileged(Native Method)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
   at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
   at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
   at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
   at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
   at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
   at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
   at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
   at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
   at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:543)
   at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
   at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
   at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:513)
   at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
   at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
   at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
   at org.mortbay.jetty.Server.doStart(Server.java:222)
   at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
   at com.sprtz.web.StartSprtzNg.main(StartSprtzNg.java:63)


I'm using OSIV (open session in view) in my web.xml, but I was thinking that since this is bean runs at startup before any web session is created, perhaps that is why Spring hasn't created one for me. Which is why I'm using openSession() instead.

However, if that's the case, then maybe Spring isn't creating a transaction for me either. So I changed my code to this:

Code:
@Repository("populateData")
@Transactional
public class PopulateData implements InitializingBean {
   
    private static final Logger log = LoggerFactory.getLogger(PopulateData.class);

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

//   @Transactional(propagation=Propagation.REQUIRES_NEW)
   public void afterPropertiesSet() throws Exception {
       log.debug("Building Member Data");
      
       Session sess = sessionFactory.openSession();
//      Session sess = sessionFactory.getCurrentSession();
       
       Transaction tx = null;
       
       try {
           tx = sess.getTransaction();
           tx.begin();
   
         for (int i = 0; i < MEMBERS.length; i++) {
            Member m= new Member();
            m.setUsername(MEMBERS[i][0]);
            m.setPassword(MEMBERS[i][0]);
            m.setCreated(new Date());
            
            Person p = new Person();
            p.setMember(m);
            p.setCreated(new Date());
            p.setFirst(MEMBERS[i][1]);
            p.setLast(MEMBERS[i][2]);
   
            m.setPerson(p);
   
            for (int j = 0; j < EMAILS[i].length; j++) {
               Email email = new Email();
               String data[] = EMAILS[i][j].split("[|]");
               email.setCreated(new Date());
               email.setName(data[0]);
               email.setValue(data[1]);
               p.addEmail(email);
            }
              sess.save(m);

              tx.commit();
         }
       }
       catch (Exception e) {
          if (tx!=null) tx.rollback();
          throw e;
       }
       finally {
          sess.close();
       }
   }

    private static final String[][] MEMBERS = {
      {"test","Test","User"},
      {"admin","Admin","User"}
   };

   private static final String[][] EMAILS = {
      {"Personal|test@test.com","Work|work@test.com","Other|test@gmail.com"},
      {"Admin|admin@test.com"}
   };
}


However, now when i run it, I get this:

Code:
org.hibernate.TransactionException: Transaction not successfully started
   at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:183)
   at com.sprtz.service.PopulateData.afterPropertiesSet(PopulateData.java:73)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
   at java.security.AccessController.doPrivileged(Native Method)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
   at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
   at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
   at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
   at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
   at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
   at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
   at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
   at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
   at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:543)
   at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
   at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
   at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:513)
   at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
   at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
   at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
   at org.mortbay.jetty.Server.doStart(Server.java:222)
   at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
   at com.sprtz.web.StartSprtzNg.main(StartSprtzNg.java:63)


So any idea what is the right way to do this?

Thanks,
Tauren


Sounie wrote:
How about trying
Code:
Session sess = factory.getCurrentSession()

instead of openSession()?

It looks like Spring should be setting a session up for you - @Transactional - but you are then establishing a new session.


--
Stephen Souness


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Fri Jul 03, 2009 1:24 pm 
Beginner
Beginner

Joined: Fri Mar 21, 2008 8:07 pm
Posts: 23
pavol.zibrita wrote:
Well, than that is just maybe a stupid question from me.
Where the spring starts and commits the transaction when you are opening session in the bean? How does he gets your session object? I don't know spring at all...

The session factory is customized by spring, and on openSession the transaction is started and registred and after bean ends, the transaction is commited?


Pavol:
No, not a stupid question. I'm just learning it all now, and don't feel like I have a complete grasp on it yet. I thought I had it all figured out, but maybe not. This could be why I'm running into problems.

But yes, my understanding is that spring uses aop to create pointcuts in the code. It intercepts the flow so that whenever a method in an @Transactional bean is called, it creates a transaction that begins before the method starts and ends after it ends. All sorts of settings can be made on a method-by-method basis using annotations, but the default is to create a read-write transaction. You can learn more here:
http://static.springsource.org/spring/d ... ction.html
http://static.springsource.org/spring/d ... nnotations

Tauren


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Fri Jul 03, 2009 1:46 pm 
Beginner
Beginner

Joined: Fri Mar 21, 2008 8:07 pm
Posts: 23
So after searching for "afterPropertiesSet spring transaction", I found this posting:
http://forum.springsource.org/showthread.php?t=49468

This indicates that afterPropertiesSet() gets run before spring has finished its work. So as an experiment, I changed things around so that my code would be run during a different part of the lifecycle, not from an InitializingBean. And now it works! My members, persons, emails, and person_emails table are all populated correctly now.

So I guess the problem was related to the session and transaction and not my mappings.

Thanks for all the help!
Tauren


Top
 Profile  
 
 Post subject: Re: Mapping table is empty
PostPosted: Sat Jul 04, 2009 7:47 am 
Regular
Regular

Joined: Sun Sep 30, 2007 7:51 pm
Posts: 93
tauren wrote:
catch (Exception e) {
if (tx!=null) tx.rollback();
throw e;
}


The exception you got was one that rollback throw. It hide another exception, so you did not saw the original one.
Better would be for the future to try catch the rollback so that you don't get another exception.

I'm glad that you solved the problem.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.