Now using JPA with a container managed entity manager.
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Mon, 18 Feb 2008 22:16:57 +0000 (22:16 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Mon, 18 Feb 2008 22:16:57 +0000 (22:16 +0000)
Also corrected the mapping for composite key with many to one.

13 files changed:
trunk/mythtv/monitor/pom.xml
trunk/mythtv/monitor/src/main/java/org/wamblee/mythtv/Channel.java
trunk/mythtv/monitor/src/main/java/org/wamblee/mythtv/Recording.java
trunk/mythtv/monitor/src/main/java/org/wamblee/mythtv/RecordingDatabase.java
trunk/mythtv/monitor/src/main/java/org/wamblee/mythtv/RecordingPk.java
trunk/mythtv/monitor/src/main/resources/META-INF/persistence.xml [new file with mode: 0644]
trunk/mythtv/war/src/main/resources/beanRefContext.xml
trunk/mythtv/war/src/main/resources/org.wamblee.mythtv.application.xml
trunk/mythtv/war/src/main/resources/org.wamblee.mythtv.datasource.xml
trunk/mythtv/war/src/main/resources/org.wamblee.mythtv.hibernate.xml
trunk/mythtv/war/src/main/resources/org.wamblee.mythtv.properties.xml
trunk/mythtv/war/src/webapp/WEB-INF/web.xml
trunk/pom.xml

index 9c031a2fc82f4f78ab9ba78cc648be10a2d0d7ab..03fa2edda744c186143deaba3a753a439c4ae6db 100644 (file)
       <groupId>javax.persistence</groupId>
       <artifactId>persistence-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-jpa</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>concurrent</groupId>
+      <artifactId>concurrent</artifactId>
+    </dependency>
     <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
index e5ef7047039fddf7e312aa2700b32117f8d1d60c..d519c9ad5461a0b897cc7134e3cc03b184f4613e 100644 (file)
@@ -28,11 +28,8 @@ import javax.persistence.Table;
 @Table(name="channel")
 public class Channel {
 
-    @Id
-    @Column(name="chanid")
     private int _id;
 
-    @Column(name="name")
     private String _name;
 
     protected Channel() {
@@ -42,17 +39,34 @@ public class Channel {
     /**
      * @return the id
      */
+    @Id
+    @Column(name="chanid")
     public int getId() {
         return _id;
     }
+    
+    /**
+     * @param aId the id to set
+     */
+    public void setId(int aId) {
+        _id = aId;
+    }
 
     /**
      * @return the name
      */
+    @Column(name="name")
     public String getName() {
         return _name;
     }
     
+    /**
+     * @param aName the name to set
+     */
+    public void setName(String aName) {
+        _name = aName;
+    }
+    
     /* (non-Javadoc)
      * @see java.lang.Object#toString()
      */
index ca0ab1cb93ed0b7e6276e60dcadc55b5e5e94841..da7220de36fa58427899eb84501e58ba32fcb844 100644 (file)
@@ -20,6 +20,7 @@ import java.io.Serializable;
 import java.util.Date;
 
 import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.IdClass;
@@ -27,36 +28,27 @@ import javax.persistence.JoinColumn;
 import javax.persistence.JoinColumns;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
 
 /**
  * 
  */
 @Entity
 @Table(name="recorded")
-//@IdClass(RecordingPk.class)
 public class Recording implements Serializable {
+    
+    private RecordingPk _id;
 
-    //@Id
-    @ManyToOne(targetEntity=Channel.class)
-    @JoinColumn(name="chanid")
-    private Channel _channel;
-    @Id
-    @Column(name="starttime")
-    private Date _starttime;
-
-    @Column(name="basename")
     private String _basename;
 
-    @Column(name="progstart")
     private Date _progstart;
 
-    @Column(name="title")
     private String _title;
-
-    @Column(name="subtitle")
+    
     private String _subtitle;
     
-    @Column(name="filesize")
     private long _filesize;
 
     protected Recording() {
@@ -66,48 +58,100 @@ public class Recording implements Serializable {
     /**
      * @return the channel
      */
-    public Channel getChannel() {
-        return _channel;
+    //@Id
+    //@ManyToOne(targetEntity=Channel.class)
+    //@JoinColumn(name="chanid")
+    
+    /**
+     * @return the id
+     */
+    @EmbeddedId
+    public RecordingPk getId() {
+        return _id;
     }
-
+    
+    /**
+     * @param aId the id to set
+     */
+    public void setId(RecordingPk aId) {
+        _id = aId;
+    }
+   
     /**
      * @return the basename
      */
+    @Column(name="basename")
     public String getBasename() {
         return _basename;
     }
-
+    
     /**
-     * @return the progstart
+     * @param aBasename the basename to set
      */
-    public Date getStartTime() {
-        return _starttime;
+    public void setBasename(String aBasename) {
+        _basename = aBasename;
     }
 
     /**
      * @return the progstart
      */
+    @Column(name="progstart")
+    @Temporal(TemporalType.TIMESTAMP)
     public Date getProgstart() {
         return _progstart;
     }
     
+    /**
+     * @param aProgstart the progstart to set
+     */
+    public void setProgstart(Date aProgstart) {
+        _progstart = aProgstart;
+    }
+    
+    @Transient
+    public Channel getChannel() { 
+        return _id.getChannel();
+    }
+    
+    @Transient
+    public Date getStarttime() { 
+        return _id.getStartTime();
+    }
+    
     /**
      * @return the title
      */
+    @Column(name="title")
     public String getTitle() {
         return _title;
     }
+    
+    /**
+     * @param aTitle the title to set
+     */
+    public void setTitle(String aTitle) {
+        _title = aTitle;
+    }
 
     /**
      * @return the subtitle
      */
+    @Column(name="subtitle")
     public String getSubtitle() {
         return _subtitle;
     }
     
+    /**
+     * @param aSubtitle the subtitle to set
+     */
+    public void setSubtitle(String aSubtitle) {
+        _subtitle = aSubtitle;
+    }
+    
     /**
      * @return the filesize
      */
+    @Column(name="filesize")
     public long getFilesize() {
         return _filesize;
     }
@@ -121,7 +165,7 @@ public class Recording implements Serializable {
      */
     @Override
     public String toString() {
-        return "Recording(" + _channel + "," + _basename + "," + _progstart + "," + _title + "," + _subtitle + ")";
+        return "Recording(" + _id + "," + _basename + "," + _progstart + "," + _title + "," + _subtitle + ")";
     }
     
     /* (non-Javadoc)
@@ -133,7 +177,7 @@ public class Recording implements Serializable {
             return false;
         }
         Recording recording = (Recording)aObj; 
-        return _channel.equals(recording._channel) && _starttime.equals(recording._starttime); 
+        return _id.equals(recording._id); 
     }
     
     /* (non-Javadoc)
@@ -141,7 +185,7 @@ public class Recording implements Serializable {
      */
     @Override
     public int hashCode() {
-        return _channel.hashCode()*10 + ((int)_starttime.getTime() %10); 
+        return _id.hashCode(); 
     }
 
 }
index 7ff517096e2659c5bf7d6a6855c3d670e311b06c..e4badfba898e40f01857b15d5ef86a8fdec18112 100644 (file)
@@ -21,6 +21,9 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.hibernate.HibernateException;
@@ -28,11 +31,13 @@ import org.hibernate.Session;
 import org.hibernate.criterion.Expression;
 import org.springframework.orm.hibernate3.HibernateCallback;
 import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
+import org.springframework.orm.jpa.JpaTemplate;
+import org.springframework.orm.jpa.support.JpaDaoSupport;
 
 /**
  * 
  */
-public class RecordingDatabase extends HibernateDaoSupport {
+public class RecordingDatabase extends JpaDaoSupport {
     
     private static final Log LOG = LogFactory.getLog(RecordingDatabase.class);
 
@@ -50,14 +55,12 @@ public class RecordingDatabase extends HibernateDaoSupport {
     }
     
     public Recording findRecording(final String aName) {
-        List<Recording> result = (List<Recording>) getHibernateTemplate().execute(new HibernateCallback() {
-           /* (non-Javadoc)
-             * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
-             */
-            public Object doInHibernate(Session aSession) throws HibernateException, SQLException {
-                return aSession.createCriteria(Recording.class).add(Expression.eq("_basename", aName)).list();
-            } 
-        });
+        JpaTemplate jpaTemplate = getJpaTemplate();
+        EntityManager entityManager = jpaTemplate.getEntityManager();
+        Query query = entityManager.createQuery(
+                "from org.wamblee.mythtv.Recording where basename = ?1");
+        query.setParameter(1, aName);
+        List<Recording> result = query.getResultList();
         if ( result.size() > 1 ) { 
             throw new RuntimeException("More than two recordings returned");
         }
@@ -68,6 +71,8 @@ public class RecordingDatabase extends HibernateDaoSupport {
     }
     
     public void update(Recording aRecording) { 
-        getHibernateTemplate().update(aRecording);
+        // Update is not required since the whole task of updating the 
+        // directory structure occurs within a single transaction. 
+        // Therefore, modifications to recordings are automatically persisted. 
     }
 }
index d47af6d70c772a43d93dd08ac770ff804e8307f8..da06d3d0d8dda0afdd386ce349117a1f4a45e343 100644 (file)
 
 package org.wamblee.mythtv;
 
+import java.io.Serializable;
 import java.util.Date;
 
 import javax.persistence.Column;
+import javax.persistence.Embeddable;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
 
 /**
  * 
  */
-public class RecordingPk {
+@Embeddable
+public class RecordingPk implements Serializable {
     public Channel _channel;
     public Date _starttime;
+    
+    public RecordingPk() { 
+        // Empty
+    }
+    
+    /**
+     * @return the channel
+     */
+    @ManyToOne
+    @JoinColumn(name="chanid")
+    public Channel getChannel() {
+        return _channel;
+    }
+    
+    /**
+     * @param aChannel the channel to set
+     */
+    public void setChannel(Channel aChannel) {
+        _channel = aChannel;
+    }
+    
+    /**
+     * @return the starttime
+     */
+    @Column(name="starttime")
+    @Temporal(TemporalType.TIMESTAMP)
+    public Date getStartTime() {
+        return _starttime;
+    }
+
+    /**
+     * @param aStarttime the starttime to set
+     */
+    public void setStartTime(Date aStarttime) {
+        _starttime = aStarttime;
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object aObj) {
+        if ( aObj == null ) { 
+            return false; 
+        }
+        if ( !(aObj instanceof RecordingPk)) { 
+            return false; 
+        }
+        RecordingPk pk = (RecordingPk) aObj;
+        return _channel.equals(pk._channel) && _starttime.equals(pk._starttime);   
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return _channel.hashCode() + _starttime.hashCode(); 
+    }
 }
diff --git a/trunk/mythtv/monitor/src/main/resources/META-INF/persistence.xml b/trunk/mythtv/monitor/src/main/resources/META-INF/persistence.xml
new file mode 100644 (file)
index 0000000..fc87ef0
--- /dev/null
@@ -0,0 +1,17 @@
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+   version="1.0">
+   <persistence-unit name="mythtv">
+      <provider>org.hibernate.ejb.HibernatePersistence</provider>
+      <jta-data-source>jdbc/mythtv</jta-data-source>
+      <class>org.wamblee.mythtv.Channel</class>
+      <class>org.wamblee.mythtv.Recording</class>
+      <exclude-unlisted-classes>true</exclude-unlisted-classes>
+      <!-- properties>
+         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
+         <property name="hibernate.show_sql" value="false"/>
+         <property name="hibernate.cache.provider" value="org.hibernate.cache.EhCacheProvider"/>
+      </properties -->
+   </persistence-unit>
+</persistence>
\ No newline at end of file
index 5288aba37e37eb4f5c771664c05efc3fca931c8d..1bd48a62aefabf3de6d1e60d2518171e0e5b48ea 100644 (file)
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans> 
+<beans xmlns="http://www.springframework.org/schema/beans"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
      
      <bean id="mythtv"
          class="org.springframework.context.support.ClassPathXmlApplicationContext">
index 1a8d0106d10fe489ff69da6d0c68ef10a3e40f0f..dafa987ddac5d42ba0bf3eecef20a8703f3249f6 100644 (file)
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
-
-<beans>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
     <bean id="linkDir" class="java.io.File">
         <constructor-arg>
@@ -24,8 +25,8 @@
 
     <bean id="org.wamblee.mythtv.RecordingDatabase" class="org.wamblee.mythtv.RecordingDatabase"
         init-method="init">
-        <property name="hibernateTemplate">
-            <ref bean="hibernateTemplate"/>
+        <property name="entityManager">
+            <ref bean="entityManager"/>
         </property>
     </bean>
 
index 9caa1c8848b792a5f2ff9484bd3a107cb2c25c9b..4f40b6d878ab1a169a23fe3e5ec02f6e7ceb65bd 100644 (file)
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
-
-<beans>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
     
     <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
         <property name="jndiName" value="${org.wamblee.mythtv.datasource}"/>
index 03a664affcd18a5b2efab6c4af67f19040eddcd9..fb66e86b18e0ca1b12fa45179b2896fac3ab9f51 100644 (file)
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
-               "http://www.springframework.org/dtd/spring-beans.dtd">
-<beans>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
        <!-- bean id="namingStrategy" class="nl.jmonks.system.hibernate.JMonksNamingStrategy"> </bean -->
 
-       <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
+       <!-- bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
                <property name="dataSource">
                        <ref bean="dataSource"/>
                </property>
@@ -16,8 +16,7 @@
                 <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                 <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                                <prop key="hibernate.query.substitutions">true 1, false 0</prop>
-                               <!-- prop key="hibernate.connection.release_mode">after_statement</prop -->
-                       </props>
+                  </props>
                </property>
                <property name="annotatedClasses">
                        <list>
                                <value>org.wamblee.mythtv.Recording</value>
                        </list>
                </property>
-               <!-- property name="namingStrategy">
-                       <ref local="namingStrategy"/>
-               </property -->
-       </bean>
+               
+       </bean -->
 
-       <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
+       <!-- bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
                <property name="sessionFactory">
                        <ref bean="sessionFactory"/>
                </property>
-       </bean>
+       </bean -->
 
        <!-- bean id="transactionManager"
                class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                <property name="sessionFactory">
                        <ref local="sessionFactory"/>
                </property>
-       </bean -->
+               </bean -->
        
+       <bean id="entityManager" class="org.springframework.jndi.JndiObjectFactoryBean">
+               <property name="jndiName"><value>java:comp/env/persistence/mythtv</value></property>
+       </bean>
+
        <bean id="transactionManager"
                class="org.springframework.transaction.jta.JtaTransactionManager">
                
index 6ba78cef98f3c0fbfd615b35f19ced8bb90b5cbe..32fa83cd6279fa61f13abb8f93e4eb921420ed82 100644 (file)
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans> 
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
     
     <bean id="propertyBean"
         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
index eb64edc6f6cd121800bc07d79de84136ca05e048..8d08eb7c19b79bc330ef9fddf7563baed54f2268 100644 (file)
@@ -9,6 +9,10 @@
         <listener-class>org.wamblee.mythtv.Application</listener-class>
     </listener>
     
+    <persistence-context-ref>
+        <persistence-context-ref-name>persistence/mythtv</persistence-context-ref-name>
+    </persistence-context-ref>
+    
     <!-- resource-ref>
         <res-ref-name>MythtvConnectionFactory</res-ref-name>
         <res-type>javax.jms.ConnectionFactory</res-type>
index 1fb054a746776b233ffb4783b475013064ac1414..753510caa55b87405cf919fef6df9aef441ca089 100644 (file)
         <version>4aug2000r7-dev</version>\r
       </dependency>\r
 \r
+      <dependency>\r
+        <groupId>concurrent</groupId>\r
+        <artifactId>concurrent</artifactId>\r
+        <version>1.3.4</version>\r
+      </dependency>\r
+\r
       <dependency>\r
         <groupId>oro</groupId>\r
         <artifactId>oro</artifactId>\r
       <dependency>\r
         <groupId>org.springframework</groupId>\r
         <artifactId>spring-hibernate3</artifactId>\r
-        <version>2.0.8</version>\r
+        <version>${springversion}</version>\r
+      </dependency>\r
+      <dependency>\r
+        <groupId>org.springframework</groupId>\r
+        <artifactId>spring-jpa</artifactId>\r
+        <version>${springversion}</version>\r
       </dependency>\r
       <dependency>\r
         <groupId>org.springframework</groupId>\r
   </repositories>\r
 \r
   <properties>\r
-    <springversion>2.5.1</springversion>\r
+    <springversion>2.0.8</springversion>\r
   </properties>\r
 \r
 </project>\r