diff --git a/pom.xml b/pom.xml index 53a26dd..b7214e3 100644 --- a/pom.xml +++ b/pom.xml @@ -70,9 +70,14 @@ org.hibernate hibernate-core - 5.1.1.Final + 5.2.2.Final compile + + org.hibernate + hibernate-c3p0 + 5.2.2.Final + org.hsqldb hsqldb diff --git a/src/main/java/musicplayer/db/HibernateDatabase.java b/src/main/java/musicplayer/db/HibernateDatabase.java index e92d10e..7dcf030 100644 --- a/src/main/java/musicplayer/db/HibernateDatabase.java +++ b/src/main/java/musicplayer/db/HibernateDatabase.java @@ -6,8 +6,11 @@ import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; -import org.hibernate.criterion.Restrictions; +import javax.persistence.NoResultException; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.*; import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -42,6 +45,11 @@ public class HibernateDatabase implements IDatabase{ properties.put("hibernate.connection.driver_class", "org.hsqldb.jdbc.JDBCDriver"); properties.put("hibernate.enable_lazy_load_no_trans", "true"); + properties.put("hibernate.c3p0.min_size", 5); + properties.put("hibernate.c3p0.max_size", 20); + properties.put("hibernate.c3p0.timeout", 300); + properties.put("hibernate.c3p0.max_statements", 50); + if(testMode){ properties.put("hibernate.connection.url", "jdbc:hsqldb:mem:."); properties.put("hibernate.hbm2ddl.auto", "create-drop"); @@ -53,7 +61,6 @@ public class HibernateDatabase implements IDatabase{ } sessionFactory = new Configuration() .addProperties(properties) - .addPackage("musicplayer.model") .addAnnotatedClass(Album.class) .addAnnotatedClass(Artist.class) .addAnnotatedClass(Song.class) @@ -75,8 +82,17 @@ public class HibernateDatabase implements IDatabase{ */ public Optional getOneAlbum(String name) { try (Session session = getSession()) { - Criteria criteria = session.createCriteria(Album.class); - Album album = (Album) criteria.add(Restrictions.eq("name", name)).uniqueResult(); + CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Album.class); + Root root = criteriaQuery.from(Album.class); + ParameterExpression parameterExpression = criteriaBuilder.parameter(String.class); + criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("name"), parameterExpression)); + TypedQuery query = session.createQuery(criteriaQuery); + query.setParameter(parameterExpression, name); + Album album = null; + try{ + album = query.getSingleResult(); + }catch(NoResultException ignored){} return (album == null) ? Optional.empty() : Optional.of(album); } } @@ -87,8 +103,17 @@ public class HibernateDatabase implements IDatabase{ */ public Optional getOneArtist(String name) { try (Session session = getSession()) { - Criteria criteria = session.createCriteria(Artist.class); - Artist artist = (Artist) criteria.add(Restrictions.eq("name", name)).uniqueResult(); + CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Artist.class); + Root root = criteriaQuery.from(Artist.class); + ParameterExpression parameterExpression = criteriaBuilder.parameter(String.class); + criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("name"), parameterExpression)); + TypedQuery query = session.createQuery(criteriaQuery); + query.setParameter(parameterExpression, name); + Artist artist = null; + try{ + artist = query.getSingleResult(); + }catch(NoResultException ignored){} return (artist == null) ? Optional.empty() : Optional.of(artist); } } @@ -99,8 +124,17 @@ public class HibernateDatabase implements IDatabase{ */ public Optional getOneSong(ExtractedMetadata metadata){ try (Session session = getSession()) { - Song song = (Song)session.createCriteria(Song.class) - .add(Restrictions.eq("songFile", metadata.getSongFile())).uniqueResult(); + CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Song.class); + Root root = criteriaQuery.from(Song.class); + ParameterExpression parameterExpression = criteriaBuilder.parameter(String.class); + criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("songFile"), parameterExpression)); + TypedQuery query = session.createQuery(criteriaQuery); + query.setParameter(parameterExpression, metadata.getSongFile()); + Song song = null; + try{ + song = query.getSingleResult(); + }catch(NoResultException ignored){} return (song == null) ? Optional.empty() : Optional.of(song); } } @@ -110,13 +144,11 @@ public class HibernateDatabase implements IDatabase{ * @param ids List of songs to keep. */ public void batchDeleteNot(Long[] ids){ - try(Session session = getSession()) { + try (Session session = getSession()) { session.beginTransaction(); - @SuppressWarnings("unchecked") - List songs = (List)session.createCriteria(Song.class).add(Restrictions.not(Restrictions.in - ("id", Arrays.asList(ids)))).list(); - if(songs != null && !songs.isEmpty()) - songs.forEach(session::delete); + //noinspection JpaQlInspection + Query query = session.createQuery("delete from Song s where s.id not in :id_list"); + query.setParameter("id_list", Arrays.asList(ids)).executeUpdate(); session.getTransaction().commit(); } } @@ -127,8 +159,17 @@ public class HibernateDatabase implements IDatabase{ */ private Optional getOneSong(Song target){ try (Session session = getSession()) { - Song song = (Song)session.createCriteria(Song.class) - .add(Restrictions.eq("songFile", target.getSongFile().toString())).uniqueResult(); + CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Song.class); + Root root = criteriaQuery.from(Song.class); + ParameterExpression parameterExpression = criteriaBuilder.parameter(String.class); + criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("songFile"), parameterExpression)); + TypedQuery query = session.createQuery(criteriaQuery); + query.setParameter(parameterExpression, target.getSongFile().toString()); + Song song = null; + try{ + song = query.getSingleResult(); + }catch(NoResultException ignored){} return (song == null) ? Optional.empty() : Optional.of(song); } } @@ -139,10 +180,14 @@ public class HibernateDatabase implements IDatabase{ * @return List of all items in the database of class typeClass. */ public Optional> listAllT(Class typeClass){ + try (Session session = getSession()) { - @SuppressWarnings("unchecked") - List output = session.createCriteria(typeClass).list(); - return (output == null || output.isEmpty()) ? Optional.empty() : Optional.of(output); + TypedQuery query = session.createQuery("select x from " + typeClass.getSimpleName() + " x", typeClass); + List result = null; + try{ + result = query.getResultList(); + }catch(NoResultException ignored){} + return (result == null || result.isEmpty()) ? Optional.empty() : Optional.of(result); } } diff --git a/src/main/java/musicplayer/library/JTreeLibrary.java b/src/main/java/musicplayer/library/JTreeLibrary.java index 844531f..8b1bb8a 100644 --- a/src/main/java/musicplayer/library/JTreeLibrary.java +++ b/src/main/java/musicplayer/library/JTreeLibrary.java @@ -25,6 +25,8 @@ import java.nio.file.Path; import java.util.*; import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @@ -39,7 +41,7 @@ public class JTreeLibrary extends JPanel implements ILibrary, LibraryCallbackInt final JTree libraryTree = new JTree(); private final Map libraryDisplayVariants = createDisplayVariantMap(); private final static Map albumArt = new ConcurrentHashMap<>(); - private Thread albumArtCollector; + private ExecutorService albumArtCollectorPool = Executors.newFixedThreadPool(2); /** * @return Map of display types for the library paired code to populate the library with data in the correct format. @@ -82,10 +84,7 @@ public class JTreeLibrary extends JPanel implements ILibrary, LibraryCallbackInt otherContainer.add(librarySearchField); this.add(otherContainer, BorderLayout.NORTH); Optional> dbQuery = database.listAllT(Album.class); - dbQuery.ifPresent(x -> x.forEach(y -> { - albumArtCollector = new Thread(() -> y.getAlbumArt().ifPresent(art -> albumArt.put(y.getId(), art))); - albumArtCollector.start(); - })); + dbQuery.ifPresent(x -> x.forEach(y -> albumArtCollectorPool.submit(new Thread(() -> y.getAlbumArt().ifPresent(art -> albumArt.put(y.getId(), art)))))); } /** @@ -216,13 +215,11 @@ public class JTreeLibrary extends JPanel implements ILibrary, LibraryCallbackInt */ public void libraryUpdated() { libraryUpdating.set(false); - albumArtCollector.interrupt(); - albumArtCollector = new Thread(() -> { - Optional> dbQuery = database.listAllT(Album.class); - dbQuery.ifPresent(x -> x.forEach(y -> y.getAlbumArt().ifPresent(art -> albumArt.put(y.getId(), - art)))); - }); - albumArtCollector.start(); + albumArtCollectorPool.shutdownNow(); + albumArtCollectorPool = Executors.newFixedThreadPool(2); + Optional> dbQuery = database.listAllT(Album.class); + dbQuery.ifPresent(x -> x.forEach(y -> albumArtCollectorPool.submit(new Thread(() -> y.getAlbumArt().ifPresent + (art -> albumArt.put(y.getId(),art)))))); refreshLibrary(); } diff --git a/src/main/java/musicplayer/model/Album.java b/src/main/java/musicplayer/model/Album.java index fc233a8..43979c2 100644 --- a/src/main/java/musicplayer/model/Album.java +++ b/src/main/java/musicplayer/model/Album.java @@ -21,6 +21,7 @@ import java.util.Optional; import java.util.Set; @Entity +@Table(name = "Album") public class Album implements Comparable, IDBType, HasSongs { @Id diff --git a/src/main/java/musicplayer/model/Artist.java b/src/main/java/musicplayer/model/Artist.java index 7eb7cb9..5f445bd 100644 --- a/src/main/java/musicplayer/model/Artist.java +++ b/src/main/java/musicplayer/model/Artist.java @@ -4,6 +4,7 @@ import javax.persistence.*; import java.util.Set; @Entity +@Table(name = "Artist") public class Artist implements Comparable, IDBType, HasSongs { @Id diff --git a/src/main/java/musicplayer/model/Song.java b/src/main/java/musicplayer/model/Song.java index b621b26..9f14ea8 100644 --- a/src/main/java/musicplayer/model/Song.java +++ b/src/main/java/musicplayer/model/Song.java @@ -4,6 +4,7 @@ import javax.persistence.*; import java.io.File; @Entity +@Table(name = "Song") public class Song implements Comparable, IDBType { @Id