我有这个数据库结构:
CREATE TABLE `archive` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`name` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`employee_id` bigint(20) NOT NULL,
`subcategory_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_pnk12l4936a21pst3p696mgt6` (`name`),
KEY `fk_archive_employee` (`employee_id`),
KEY `fk_archive_subcategory` (`subcategory_id`)
)
CREATE TABLE `archive_file` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`created` datetime NOT NULL,
`edition` varchar(4) COLLATE utf8_unicode_ci NOT NULL,
`expire` date NOT NULL,
`history` text COLLATE utf8_unicode_ci NOT NULL,
`mime_type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`archive_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_lgh85dj5mtjkevbkmgl8q0rso` (`name`),
KEY `fk_archive_file_archive` (`archive_id`)
)
这个java实体:
Archive.java
@Entity
@Table(name = "archive")
public class Archive extends AbstractEntity {
@NotEmpty
@Size(max = ConstantNumeric.TWO_HUNDRED)
@Column(name = "name", length = ConstantNumeric.TWO_HUNDRED, unique = true)
private String name;
@NotEmpty
@ManyToOne
@JoinColumn(name = "subcategory_id")
@ForeignKey(name = FK + "subcategory")
private ArchiveCategory subcategory;
@NotEmpty
@OneToMany(mappedBy = "archive", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
private List<ArchiveFile> files;
@NotEmpty
@ManyToOne
@JoinColumn(name = "employee_id")
@ForeignKey(name = FK + "employee")
private Employee responsible;
@NotEmpty
@AuditJoinTable(inverseJoinColumns = @JoinColumn(name = "department_id"))
@ManyToMany
@JoinTable(name = "archive_has_department", joinColumns = @JoinColumn(name = "archive_id"),
inverseJoinColumns = @JoinColumn(name = "department_id"))
@ForeignKey(name = FK + "has_department", inverseName = FK + "department")
private List<Department> departments;
...Getters/Settters
ArchiveFile.java
@Entity
@Table(name = "archive_file")
public class ArchiveFile extends AbstractEntity {
@NotEmpty
@Size(max = ConstantNumeric.TWO_HUNDRED)
@Column(name = "name", unique = true, length = ConstantNumeric.TWO_HUNDRED, updatable = false)
private String name;
@NotEmpty
@Size(max = ConstantNumeric.FOUR)
@Column(name = "edition", length = ConstantNumeric.FOUR, updatable = false)
private String edition;
@NotEmpty
@Temporal(TemporalType.DATE)
@Column(name = "expire", updatable = false)
private Date expire;
@NotEmpty
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created", updatable = false)
private Date created;
@NotEmpty
@Column(columnDefinition = "text", updatable = false)
private String history;
@NotEmpty
@ManyToOne(cascade = CascadeType.ALL, optional = false)
@JoinColumn(name = "archive_id", referencedColumnName = "id")
@ForeignKey(name = "fk_archive_file_archive")
private Archive archive;
@NotEmpty
@Column(name = "mime_type", updatable = false)
private String mimeType;
...Getters/Settters
有了这个我需要所有档案与最后创建的archive_file 一个SQL查询来执行此操作,例如:
SELECT * FROM archive AS a
INNER JOIN archive_file as af
WHERE af.id IN(SELECT a.id FROM
(SELECT * FROM archive_file AS af WHERE af.created > '2012-05-30'
ORDER BY af.created DESC) AS a GROUP BY a.archive_id) AND a.id = af.archive_id
结果是:
+----+---------+--------------------------+-------------+----------------+----+---------+---------------------+---------+------------+-----------------------+--------------+-----------------+------------+
| id | version | name | employee_id | subcategory_id | id | version | created | edition | expire | history | mime_type | name | archive_id |
+----+---------+--------------------------+-------------+----------------+----+---------+---------------------+---------+------------+-----------------------+--------------+-----------------+------------+
| 1 | 1 | Archive shouldUpdateDAO | 1 | 4 | 1 | 0 | 2014-05-31 14:41:27 | 1 | 2014-06-04 | history sholdSaveDAO | document/pdf | SHOULDSAVEDAO | 1 |
| 2 | 0 | Archive ShouldGetByIdDAO | 1 | 2 | 3 | 0 | 2014-05-30 14:41:27 | 1 | 2014-05-30 | history shouldGetById | document/pdf | SHOUDGETBYIDDAO | 2 |
+----+---------+--------------------------+-------------+----------------+----+---------+---------------------+---------+------------+-----------------------+--------------+-----------------+------------+
2 rows in set (0.00 sec)
但是我需要用JPQL来做这件事,我试过这个没有成功:
final String sql = "SELECT archive FROM archive AS a INNER JOIN archive_file as af " +
"WHERE af.id in (SELECT a.id FROM (SELECT archive_file FROM archive_file AS af " +
"WHERE af.created > '2012-05-30' ORDER BY af.created DESC) AS a " +
"GROUP BY a.archive_id) AND a.id = af.archive_id";
TypedQuery<Archive> query = getEm().createQuery(sql, Archive.class);
抛出异常,因为这不是有效的JPQL查询:
javax.ejb.EJBException:java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException:意外令牌: (靠近第1行,第97列[SELECT archive FROM archive as a INTERNER JOIN archive_file as af WHERE af.id in(SELECT a.id FROM(SELECT archive_file FROM archive_file AS af af afcreated&gt; '2012-05-30' ORDER BY af.created DESC)as a group by a.archive_id)AND a.id = af.archive_id]
有一种方法可以在JPQL中执行此操作吗?如果没有,你会用什么方法? SQL本机查询,Criteria还是什么?
答案 0 :(得分:0)
你需要什么subquerys?
仅使用内连接不会起作用吗?
SELECT
*
FROM
archive AS a
INNER JOIN
archive_file as af ON af.archive_id= a.id
WHERE
af.created > '2012-05-30'
猜测我没有任何数据。
没有subquerys的查询可能如下所示:
SELECT
a.*, af.id as aid, af.created, af.archive_id
FROM
archive AS a
INNER JOIN
archive_file as af ON af.archive_id= a.id
LEFT JOIN
archive_file as af2 ON af2.archive_id= af.archive_id
AND af2.created > af.created
WHERE
af.created > '2012-05-30' and
af2.created is null
sql fiddle here
答案 1 :(得分:0)
您的SQL查询可以重写为:
SELECT DISTINCT a.* FROM archive a, archive_file af WHERE a.id = af.archive_id AND af.created > '2012-05-30'
它映射到以下JPQL查询:
SELECT DISTINCT a FROM archive a WHERE a.files.created > '2012-05-30'