目前,JPQL
查询的联接中的所有文章均以getRangeOfArticles
方式返回,而只有范围的文章应该得到回报。
我正在使用MySQL控制台输出,但想在JPQL中实现:
mysql>
mysql> SELECT * FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist" AND articles.ID BETWEEN 450 AND 453;
+-----+---------------+--------------+------+---------------------+
| ID | MESSAGENUMBER | NEWSGROUP_ID | ID | NEWSGROUP |
+-----+---------------+--------------+------+---------------------+
| 450 | 554 | 5 | 5 | gwene.com.economist |
| 451 | 555 | 5 | 5 | gwene.com.economist |
| 452 | 556 | 5 | 5 | gwene.com.economist |
| 453 | 557 | 5 | 5 | gwene.com.economist |
+-----+---------------+--------------+------+---------------------+
4 rows in set (0.02 sec)
mysql>
mysql> show tables;
+------------------+
| Tables_in_usenet |
+------------------+
| articles |
| newsgroups |
+------------------+
2 rows in set (0.01 sec)
mysql> describe articles;
+---------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| MESSAGENUMBER | int(11) | YES | | NULL | |
| NEWSGROUP_ID | bigint(20) | YES | MUL | NULL | |
+---------------+------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> describe newsgroups;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| NEWSGROUP | varchar(255) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql>
我正试图在getRangeOfArticles
方法中用JPQL复制那个SQL查询:
package net.bounceme.dur.usenet.driver;
import java.util.List;
import java.util.logging.Logger;
import javax.mail.Folder;
import javax.mail.Message;
import javax.persistence.*;
import net.bounceme.dur.usenet.model.Article;
import net.bounceme.dur.usenet.model.Newsgroup;
class DatabaseUtils {
private static final Logger LOG = Logger.getLogger(DatabaseUtils.class.getName());
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("USENETPU");
private EntityManager em = emf.createEntityManager();
//SELECT MAX(MESSAGENUMBER) FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist";
public int getMaxMessageNumber(Folder folder) {
int maxMessageNumber = 0;
String newsgroup = folder.getFullName();
String queryString = "select max(article.messageNumber) from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = '" + newsgroup + "'";
try {
maxMessageNumber = (Integer) em.createQuery(queryString).getSingleResult();
} catch (Exception e) {
LOG.severe("setting max to zero for " + newsgroup);
}
LOG.fine(folder.getFullName() + "\t" + maxMessageNumber);
return maxMessageNumber;
}
//SELECT * FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist" AND articles.ID BETWEEN 450 AND 500;
public List<Article> getRangeOfArticles(Page page) {
String fullNewsgroupName = page.getFolder().getFullName();
int minRange = page.getMin();
int maxRange = page.getMax();
String queryString = "select article from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = :newsGroupParam";
TypedQuery<Article> query = em.createQuery(queryString, Article.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
List<Article> results = query.getResultList();
LOG.info(results.toString());
return results;
}
public void persistArticle(Message message, Folder folder) {
em.getTransaction().begin();
String fullNewsgroupName = folder.getFullName();
Newsgroup newsgroup = null;
TypedQuery<Newsgroup> query = em.createQuery("SELECT n FROM Newsgroup n WHERE n.newsgroup = :newsGroupParam", Newsgroup.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
try {
newsgroup = query.getSingleResult();
LOG.fine("found " + query.getSingleResult());
} catch (javax.persistence.NoResultException e) {
LOG.fine(e + "\ncould not find " + fullNewsgroupName);
newsgroup = new Newsgroup(folder);
em.persist(newsgroup);
} catch (NonUniqueResultException e) {
LOG.warning("\nshould never happen\t" + fullNewsgroupName);
} /*
* finally { if (em.getTransaction().isActive()) {
* em.getTransaction().rollback(); }
*/
Article article = new Article(message, newsgroup);
em.persist(article);
em.getTransaction().commit();
}
public void close() {
em.close();
emf.close();//necessary?
}
}
答案 0 :(得分:1)
如果您想以Article
的名称查询Newsgroup
的集合,可以执行以下操作:
String queryString = "select a from Article a where a.newsgroup.newsgroup = :newsGroupParam";
TypedQuery<Article> query = em.createQuery(queryString, Article.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
List<Article> results = query.getResultList();
不要在JPQL中编写联接,让JPA为您完成工作。
作为额外提示,您应该始终编写这样的查询以防止SQL注入。
public int getMaxMessageNumber(Folder folder) {
int maxMessageNumber = 0;
String queryString = "select max(a.messageNumber) from Article a where a.newsgroup.newsgroup = :newsgroup";
Query q = em.createQuery(queryString);
q.setParameter("newsgroup", folder.getFullName());
try {
maxMessageNumber = (Integer) q.getSingleResult();
} catch (Exception e) {
LOG.severe("setting max to zero for " + newsgroup);
}
LOG.fine(folder.getFullName() + "\t" + maxMessageNumber);
return maxMessageNumber;
}
答案 1 :(得分:0)
就查询而言,我相信它是String queryString = "select article from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = :newsGroupParam and article.messageNumber between 100 and 500";
,虽然我需要在其中添加一些参数作为范围。请参阅下面的getRangeOfArticles
:
package net.bounceme.dur.usenet.driver;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.persistence.*;
import net.bounceme.dur.usenet.model.Article;
import net.bounceme.dur.usenet.model.Newsgroup;
import net.bounceme.dur.usenet.model.Usenet;
class DatabaseUtils {
private static final Logger LOG = Logger.getLogger(DatabaseUtils.class.getName());
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("USENETPU");
private EntityManager em = emf.createEntityManager();
//SELECT MAX(MESSAGENUMBER) FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist";
public int getMaxMessageNumber(Folder folder) {
int maxMessageNumber = 0;
String newsgroup = folder.getFullName();
String queryString = "select max(article.messageNumber) from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = '" + newsgroup + "'";
try {
maxMessageNumber = (Integer) em.createQuery(queryString).getSingleResult();
} catch (Exception e) {
LOG.severe("setting max to zero for " + newsgroup);
}
LOG.fine(folder.getFullName() + "\t" + maxMessageNumber);
return maxMessageNumber;
}
//SELECT * FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist" AND articles.ID BETWEEN 450 AND 500;
public List<Article> getRangeOfArticles(Page page) {
String fullNewsgroupName = page.getFolder().getFullName();
int minRange = page.getMin();
int maxRange = page.getMax();
String queryString = "select article from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = :newsGroupParam and article.messageNumber between 100 and 500";
TypedQuery<Article> query = em.createQuery(queryString, Article.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
List<Article> articles = query.getResultList();
Usenet usenet = Usenet.INSTANCE;
for (Article article : articles) {
List<String> string = new ArrayList<>();
string.add(article.getId().toString());
string.add(Long.toString(article.getMessageNumber()));
Message message = usenet.getMessage(page.getFolder(), article.getMessageNumber());
try {
string.add(message.getSubject());
} catch (MessagingException ex) {
Logger.getLogger(DatabaseUtils.class.getName()).log(Level.SEVERE, null, ex);
}
Newsgroup n = article.getNewsgroup();
string.add(n.getNewsgroup());
LOG.info(string.toString());
}
return articles;
}
public void persistArticle(Message message, Folder folder) {
em.getTransaction().begin();
String fullNewsgroupName = folder.getFullName();
Newsgroup newsgroup = null;
TypedQuery<Newsgroup> query = em.createQuery("SELECT n FROM Newsgroup n WHERE n.newsgroup = :newsGroupParam", Newsgroup.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
try {
newsgroup = query.getSingleResult();
LOG.fine("found " + query.getSingleResult());
} catch (javax.persistence.NoResultException e) {
LOG.fine(e + "\ncould not find " + fullNewsgroupName);
newsgroup = new Newsgroup(folder);
em.persist(newsgroup);
} catch (NonUniqueResultException e) {
LOG.warning("\nshould never happen\t" + fullNewsgroupName);
} /*
* finally { if (em.getTransaction().isActive()) {
* em.getTransaction().rollback(); }
*/
Article article = new Article(message, newsgroup);
em.persist(article);
em.getTransaction().commit();
}
public void close() {
em.close();
emf.close();//necessary?
}
}
但是,我似乎遇到了一些错误:
Aug 06, 2012 12:00:02 AM net.bounceme.dur.usenet.model.Usenet getMessage
SEVERE: null
javax.mail.MessageRemovedException: No such article: 273
所以可能是查询语法或含义出错,或者我有逻辑错误。