每个User
都有一个Box
。每个Box
可能包含一些Item
我的架构是:
Item
:
@Entity
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
@ManyToOne(fetch=FetchType.LAZY)
@Column(allowsNull = "false")
@Unowned
private Box location;
...
Box
:
@Entity
public class Box {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
@OneToMany(mappedBy="location", cascade={CascadeType.ALL})
private List<Item> items;
...
User
:
@Entity
public class User{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
@OneToOne(fetch=FetchType.LAZY, cascade={CascadeType.REMOVE})
@Column(allowsNull = "false")
@JoinColumn(name="BOX_ID")
private Box box;
如果此结构中有任何错误,请告诉我。
现在我想要检索属于Item
的所有User
,最好使用javax.persistence.EntityManager
,但我根本不能。
我打算做的是:
Query q1 = em.createQuery("select u from User u where u.username='"+username+"'");
User user = // ... well known code
Query q2 = em.createQuery("select i from Item i where i.location='"+user.box+"'");
Item item = // ... well known code
现在我收到了这个例外:
SELECT u FROM database.entities.Item u WHERE u.location.key='database.entities.Box@3872bb09': Can only reference properties of a sub-object if the sub-object is embedded.
答案 0 :(得分:1)
首先,您不应该使用连接将动态参数传递给查询。这是低效的,如果参数包含单引号将失败,并打开您的代码到SQL注入攻击。使用命名参数:
select ... where u.username = :name
...
query.setParameter("name", username);
现在看看你的第二个查询。它搜索的项目的位置等于Box实例的toString()值。这没有意义。您必须将框作为参数传递:
Query q2 = em.createQuery("select i from Item i where i.location = :box");
q2.setParameter("box", user.getBox());
请注意,您不需要两个查询。一个就足够了:
select item from User user
inner join user.box box
inner join box.items item
where user.username = :name