Java Hibernate连接和对多个表的限制
我有三个表要用Hibernate或JPA查询 表结构Java Hibernate连接和对多个表的限制,java,hibernate,hibernate-criteria,Java,Hibernate,Hibernate Criteria,我有三个表要用Hibernate或JPA查询 表结构 CREATE TABLE `product` ( `product_id` int(11) NOT NULL AUTO_INCREMENT, `insert_date` datetime NOT NULL, `last_update` datetime NOT NULL, ... PRIMARY KEY (`product_id`) ) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHA
CREATE TABLE `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`insert_date` datetime NOT NULL,
`last_update` datetime NOT NULL,
...
PRIMARY KEY (`product_id`)
) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8;
CREATE TABLE `language` (
`language_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
...
PRIMARY KEY (`language_id`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `product_description` (
`product_id` int(11) unsigned NOT NULL,
`language_id` int(11) unsigned NOT NULL,
`name` varchar(255) NOT NULL,
`description` text NOT NULL,
`tag` text NOT NULL,
`meta_title` varchar(255) NOT NULL,
`meta_description` varchar(255) NOT NULL,
`meta_keyword` varchar(255) NOT NULL,
PRIMARY KEY (`product_id`,`language_id`),
KEY `name` (`name`),
KEY `product_language_idx` (`language_id`),
CONSTRAINT `product_description` FOREIGN KEY (`product_id`) REFERENCES `product` (`product_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `product_language` FOREIGN KEY (`language_id`) REFERENCES `language` (`language_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Product <OneToMany> ProductDescription
Language <ManyToOne> ProductDescription
ProductDescription实体(id是ProductDescriptionPK类中的复合键):
首先,我使用了Hibernate和条件查询:
Criteria criteria = getSession().createCriteria(Product.class,"p");
criteria.createAlias("p.productDescriptions", "pd");
criteria.createAlias("pd.languages", "l");
criteria.add(Restrictions.eq("l.languageId", new Integer(1)));
result = criteria.list();
但该代码检索此错误:
原因:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
“字段列表”中的未知列“l2\产品描述\语言\ id”
我的问题是什么?我如何执行这样的查询
非常感谢 我不完全理解您的数据模型。 我认为从
语言
的角度来看,语言
和产品描述
之间的关系应该是一对多的关系,但把它放在一边
已更新:
实际上,Hibernate无法使用上面指出的注释正确映射关系。它试图在表语言中映射奇怪的manytone关系,但找不到以下字段:productDescription\u language\u id
和productDescription\u product\u id
我认为您的表的正确映射是:
语言实体
@Entity
public class Language {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="language_id", unique=true, nullable=false)
private Long languageId;
private String name;
@OneToMany(fetch=FetchType.LAZY, mappedBy="language")
private List<ProductDescription> productDescriptions =
new ArrayList<ProductDescription>();
// Other fields + getters and setters
}
@Entity
@Table(name="product_description")
public class ProductDescription {
@Embeddable
public static class ProductDescriptionPK implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "product_id")
protected Long productId;
@Column(name = "language_id")
protected Long languageId;
public ProductDescriptionPK() {
}
public ProductDescriptionPK(Long productId, Long languageId) {
super();
this.productId = productId;
this.languageId = languageId;
}
}
@EmbeddedId
private ProductDescriptionPK id;
private String description;
@ManyToOne
@JoinColumn(name="language_id", nullable=false, insertable=false, updatable=false)
private Language language;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="product_id", nullable=false, insertable=false, updatable=false)
private Product product;
// Other fields + getters and setters
}
下面是一个工作示例,说明如何使用在问题中声明的实体来链接JPQL
EntityManager em = emf.createEntityManager();
// [UPDATED] QUERY
String jpql = "SELECT p.id, pd.description FROM Product p "
+ "JOIN p.productDescriptions pd "
+ "JOIN pd.language l WHERE l.language_id = :idLanguage)";
Query query = newEm.createQuery(jpql);
query.setParameter("idLanguage", new Long(1));
List<Object> resultList = query.getResultList();
System.out.println( resultList.size() + " product(s) found:" );
for (Object singleResult : resultList) {
Object[] singleRow = (Object[]) singleResult;
System.out.println(singleRow[0] + " " + singleRow[1]);
}
我一直在阅读一些关于这个主题的文章和书籍,使用带有where子句的左连接fetch是无效的。引用Gavin King等人的“带Hibernate的Java持久性”:
“查询left join fetch i.bids b其中b.amount
…无效。您不能说,“加载项
实例并初始化其投标集合,但只能使用具有特定金额的Bid
实例”
希望这能有所帮助。你为什么不试试JPQL呢?我想你可以很容易地完成你的查询。现在没有时间用JPQL测试你的示例中的rigth查询,但是这个答案可能对你有用。我同意你的看法。你能得到我的示例吗?呃,我认为链接后面有一个示例。你有产品ProductDescription语言。以及前面提到的链接go Category主题帖子。因此,对于具有多个联接和on join字段条件的查询,我必须使用createQuery?如果要使用JPQL定义查询,您需要使用createQuery。您可能可以定义一个条件,但需要更多的代码行。谢谢Rubio,但我使用的是Hibernate它无法处理此错误“on子句”中的未知列“languages2\u.productDescription\u language\u id”。pd.ProductDescriptions中的Languages属性是List@antonio我也使用了Hibernate。请更新上面的问题,添加表结构、每个表的含义和执行的查询。我将尝试修改我的答案是正确的。@antonio我已经更新了我的答案。请检查一下。我如何在我的DAO中使用EntityManager?我只创建了一个sessionFactory Spring Bean,所以我无法实例化EntityManager,你能解释它是如何工作的吗?@antonio你可以用会话替换EntityManager来创建查询。从你的工厂获取会话并调用session.createQuery。
Criteria criteria = getSession().createCriteria(Product.class,"p");
criteria.createAlias("p.productDescriptions", "pd");
criteria.createAlias("pd.languages", "l");
criteria.add(Restrictions.eq("l.languageId", new Integer(1)));
result = criteria.list();
@Entity
public class Language {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="language_id", unique=true, nullable=false)
private Long languageId;
private String name;
@OneToMany(fetch=FetchType.LAZY, mappedBy="language")
private List<ProductDescription> productDescriptions =
new ArrayList<ProductDescription>();
// Other fields + getters and setters
}
@Entity
@Table(name="product_description")
public class ProductDescription {
@Embeddable
public static class ProductDescriptionPK implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "product_id")
protected Long productId;
@Column(name = "language_id")
protected Long languageId;
public ProductDescriptionPK() {
}
public ProductDescriptionPK(Long productId, Long languageId) {
super();
this.productId = productId;
this.languageId = languageId;
}
}
@EmbeddedId
private ProductDescriptionPK id;
private String description;
@ManyToOne
@JoinColumn(name="language_id", nullable=false, insertable=false, updatable=false)
private Language language;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="product_id", nullable=false, insertable=false, updatable=false)
private Product product;
// Other fields + getters and setters
}
EntityManager em = emf.createEntityManager();
// [UPDATED] QUERY
String jpql = "SELECT p.id, pd.description FROM Product p "
+ "JOIN p.productDescriptions pd "
+ "JOIN pd.language l WHERE l.language_id = :idLanguage)";
Query query = newEm.createQuery(jpql);
query.setParameter("idLanguage", new Long(1));
List<Object> resultList = query.getResultList();
System.out.println( resultList.size() + " product(s) found:" );
for (Object singleResult : resultList) {
Object[] singleRow = (Object[]) singleResult;
System.out.println(singleRow[0] + " " + singleRow[1]);
}
select
product0_.product_id as col_0_0_,
productdes1_.description as col_1_0_
from
Product product0_
inner join
product_description productdes1_
on product0_.product_id=productdes1_.product_id
inner join
Language language2_
on productdes1_.language_id=language2_.language_id
where
language2_.language_id=?