Also corrected the mapping for composite key with many to one.
<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>
@Table(name="channel")
public class Channel {
- @Id
- @Column(name="chanid")
private int _id;
- @Column(name="name")
private String _name;
protected 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()
*/
import java.util.Date;
import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
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() {
/**
* @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;
}
*/
@Override
public String toString() {
- return "Recording(" + _channel + "," + _basename + "," + _progstart + "," + _title + "," + _subtitle + ")";
+ return "Recording(" + _id + "," + _basename + "," + _progstart + "," + _title + "," + _subtitle + ")";
}
/* (non-Javadoc)
return false;
}
Recording recording = (Recording)aObj;
- return _channel.equals(recording._channel) && _starttime.equals(recording._starttime);
+ return _id.equals(recording._id);
}
/* (non-Javadoc)
*/
@Override
public int hashCode() {
- return _channel.hashCode()*10 + ((int)_starttime.getTime() %10);
+ return _id.hashCode();
}
}
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;
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);
}
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");
}
}
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.
}
}
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();
+ }
}
--- /dev/null
+<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
<?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">
<?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>
<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>
<?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}"/>
<?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>
<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">
<?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">
<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>
<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