我正在进行LEFT OUTER JOIN,但我只能在第一个表上应用Restrictions.有没有办法在第二张桌子上申请?
这是我的代码:
Criteria criteria = this.crudService
.initializeCriteria(Applicant.class).setFetchMode("products",
FetchMode.JOIN);.
Run Code Online (Sandbox Code Playgroud)
这工作(申请人有applicantName属性):
criteria.add(Restrictions.eq("applicantName", "Markos")
Run Code Online (Sandbox Code Playgroud)
这些都不起作用(产品具有productName属性)
criteria.add(Restrictions.eq("productName", "product1")
Run Code Online (Sandbox Code Playgroud)
criteria.add(Restrictions.eq("products.productName","product1")// products:属性的名称criteria.add(Restrictions.eq("Product.productName","product1")//产品:数据库表的名称
这是我收到的例外(如果我理解正确),申请人中不存在productName属性:
EJB Exception: ; nested exception is: org.hibernate.QueryException: could not resolve property: products.inventedName of: org.myCompany.applicant.entity.Applicant; nested exception is: org.hibernate.QueryException: could not resolve property: products.inventedName of: org.myCompany.applicant.entity.Applicant
Run Code Online (Sandbox Code Playgroud)
我尝试使用别名,但这会生成一个INNER JOIN,而不是我想要的LEFT OUTER JOIN.
如何对两个表格施加限制?
更新:
问题可能与此相同:https: //forum.hibernate.org/viewtopic.php?p = 2393694
我正在使用Criteria API检索hibernate中的对象列表.但是我需要锁定这些对象,因为同时执行的另一个线程将获得确切的对象,并且只有一个线程将在没有悲观锁定的情况下成功.
我尝试过如下,但它不起作用.
List esns = session
.createCriteria(Reddy_Pool.class)
.add(Restrictions.eq("status", "AVAILABLE"))
.add(Restrictions.eq("name", "REDDY2"))
.addOrder(Order.asc("id"))
.setMaxResults(n)
.setLockMode(LockMode.PESSIMISTIC_WRITE) //not working at all
.list();
Run Code Online (Sandbox Code Playgroud)
更新:我在此语句之后执行更新,因此我希望两个线程都读取不同的行,或者至少第二个线程应该等到第一个线程完成事务并离开锁.
而hibernate生成的查询如下.
Hibernate: select this_.id as id1_0_, this_.name as name1_0_,
this_.orderitem_id as orderitem3_1_0_, this_.status as status1_0_,
this_.store as store1_0_, this_.vendor as vendor1_0_, this_.version as version1_0_
from reddy_pool this_
where this_.status=? and and this_.name=? order by this_.id asc limit ?
Run Code Online (Sandbox Code Playgroud)
更新:这似乎是3.5.2版本中的一个错误,因为Pascal Thivent(非常感谢Pascal)提到过,我已经加入成为会员并观看了这个问题.希望它将包含在下一个版本中.
然而,我尝试使用另一种方法session.buildLockRequest()...但我无法弄清楚如何使用它并使用下面的代码根本没有任何影响.
for (int i=0; i < n; i++)
session.buildLockRequest(LockOptions.UPGRADE).lock(esns.get(i));
Run Code Online (Sandbox Code Playgroud) 我有一个Hibernate条件调用,我想在一个SQL语句中执行.我正在尝试做的是选择Parent的实例,其中Child具有一系列值的属性(SQL IN子句),所有这些都是在使用外连接加载子项时.这是我到目前为止所拥有的:
Criteria c = session.createCriteria(Parent.class);
c.createAlias("children", "c", CriteriaSpecification.LEFT_JOIN)
.setFetchMode("c", FetchMode.JOIN)
.add(Restrictions.in("c.property", properties));
c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return c.list();
Run Code Online (Sandbox Code Playgroud)
这是一些示例数据:
Parent
Parent ID
A
B
C
Children
Child ID Parent ID property
... A 0
... A 2
... A 7
... B 1
... C 1
... C 2
... C 3
Run Code Online (Sandbox Code Playgroud)
我想要做的是如果其中一个孩子的属性等于我的绑定参数,则返回父母及其所有孩子.我们假设属性是一个包含{2}的数组.在这种情况下,调用将返回父A和C,但他们的子集只包含元素2.即父[子]:
A [2]&C [2]
我想要的是:
A [0,2,7]&C [1,2 3]
如果这不是一个bug,它似乎是一个破碎的语义.我不知道如何调用A.getChildren()或C.getChildren()并返回1条记录将被认为是正确的 - 这不是一个投影.即如果我扩充查询以使用默认的选择提取,它将返回正确的子集合,带有大量查询的albiet:
c.createAlias("children", "c").add(
Restrictions.in("c.property", properties));
Run Code Online (Sandbox Code Playgroud)
这是一个错误吗?如果没有,我怎样才能达到预期的效果呢?
我正在使用JPA2和它的Criteria API来从数据库中选择我的实体.实现是WebSphere Application Server上的OpenJPA.我的所有实体都使用Fetchtype = Lazy建模.
我从数据库中选择一个具有某些条件的实体,并希望一次从子表中加载所有嵌套数据.如果我有一个数据模型,其中表A将oneToMany连接到表B,我可以在条件查询中使用Fetch子句:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<A> cq = cb.createQuery(A.class);
Root<A> root = cq.from(A.class);
Fetch<A,B> fetch = root.fetch(A_.elementsOfB, JoinType.LEFT);
Run Code Online (Sandbox Code Playgroud)
这很好用.我得到一个元素A,它的所有元素都被正确填充.现在表B与表C具有oneToMany关系,我也想加载它们.所以我在我的查询中添加以下语句:
Fetch<B,C> fetch2 = fetch.fetch(B_.elementsOfC, JoinType.LEFT);
Run Code Online (Sandbox Code Playgroud)
但这不会做任何事情.
有人知道如何在一个查询中获取多级实体吗?
我正在尝试使用注释的一对一关系.
这是代码.
package test.hibernate;
@Entity
@Table(name="EMPLOYEE")
public class Employee {
@Id
@GeneratedValue
@Column(name="EMP_ID")
private Long empID;
@Column(name="fName")
private String fName;
@Column(name="lName")
private String lName;
@OneToOne(mappedBy="employee", cascade=CascadeType.ALL)
private Address address;
public Employee(/* Long empID, */String fName, String lName) {
super();
// this.empID = empID;
this.fName = fName;
this.lName = lName;
}
public Employee() {
super();
}
public Long getEmpID() {
return empID;
}
public void setEmpID(Long empID) {
this.empID = empID;
}
public String getfName() {
return fName;
}
public void …Run Code Online (Sandbox Code Playgroud) 我有一个带有事件列表的java实体类UserBean:
@OneToMany
private List<EventBean> events;
Run Code Online (Sandbox Code Playgroud)
EventBean有Date变量:
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date eventDate;
Run Code Online (Sandbox Code Playgroud)
现在在UserBean中,我想创建一个NamedQuery,它返回特定范围内的所有日期:
@NamedQuery(name="User.findEventsWithinDates",
query="SELECT u.events FROM UserBean u WHERE u.name = :name AND u.events.eventDate > :startDate AND u.events.eventDate < :endDate")
Run Code Online (Sandbox Code Playgroud)
上面的查询不能编译.我收到此错误:
The state field path 'u.events.eventDate' cannot be resolved to a valid type.
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我使用EclipseLink版本2.5.0.v20130507-3faac2b.
我该怎么做才能使这个查询工作?谢谢.
文档说:
为文字创建表达式
在代码中我看到了cb.literal()的此类用法:
Expression<String> wordLiteral = cb.literal(word);
predicates.add(cb.like(namePath, wordLiteral));
Run Code Online (Sandbox Code Playgroud)
但如果这里省略wordLiteral并使用word代替,则不会发生任何变化。那么这个方法是做什么用的呢?
我们正在使用hracle与oracle(11),并且由于使用了'ilike',不区分大小写'喜欢'而导致严重的性能问题.
java/hibernate代码如下所示:
c1.add( Restrictions.ilike("address", address) );
Run Code Online (Sandbox Code Playgroud)
这导致sql语句如
select * from ACCOUNT where lower(ADDRESS_1) = ?
Run Code Online (Sandbox Code Playgroud)
'lower'函数使oracle无法使用导致全表扫描的索引.
我正在考虑向db表引入一个新列,其中包含小写的地址内容.然后我可以使用:
c1.add( Restrictions.ilike("addressLCase", address.toLowerCase()) );
Run Code Online (Sandbox Code Playgroud)
...但我真的不喜欢将内容存储两次的想法......
然后我想到用小写创建一个索引
CREATE INDEX ADDRESS_1_IDX ON ACCOUNT lower( ADDRESS_1 ) ;
Run Code Online (Sandbox Code Playgroud)
但是这没用,因为我无法说服优化器使用这个索引......
那么我该如何使用hibernate准则API和'ilike'创建快速查询?
我想要一个Criteria查询来使用AliasToBeanResultTransformer实例化一个DTO类.目标是生成一个轻量级分页列表,其中包含用于主页进一步操作的ID.这需要报告类型查询.
Criteria crit = session.createCriteria(Profile.class);
crit.createAlias("personalData", "pd");
crit.createAlias("emails", "e");
crit.createAlias("telephones", "t");
ProjectionList properties = Projections.projectionList();
properties.add(Projections.property("id").as( "id"));
properties.add(Projections.property("pd.lastName").as("lastName"));
properties.add(Projections.property("pd.fullName").as("fullName"));
properties.add(Projections.property("e.emailAddress").as("email"));
properties.add(Projections.property("t.phoneNumber").as("phone"));
crit.setProjection(properties);
crit.setResultTransformer(new AliasToBeanResultTransformer(ProfileDTO.class));
profiles = crit.list();
Run Code Online (Sandbox Code Playgroud)
这无法实例化我的DTO类.ProfileDTO有一个匹配的构造函数:
public ProfileDTO(Long id, String lastName, String fullName, String email,
String phone) {
this(id,fullName);
this.lastName = lastName;
this.email = email;
this.phone = phone;
}
Run Code Online (Sandbox Code Playgroud)
当我使用结果行手动构造ProfileDTO对象时,查询有效
List<Object[]> rows = crit.list();
for ( Object[] row: rows ) {
ProfileDTO dto = new ProfileDTO();
dto.setId((Long)row[0]);
dto.setLastName((String)row[1]);
dto.setFullName((String)row[2]);
dto.setEmail((String)row[3]);
dto.setPhone((String)row[4]);
profiles.add(dto);
}
Run Code Online (Sandbox Code Playgroud)
我的解决方法工作正常,但似乎没必要.我究竟做错了什么?
hibernate ×6
jpa ×3
criteria-api ×2
java ×2
criteria ×1
eclipselink ×1
fetch ×1
join ×1
jpa-2.0 ×1
jpql ×1
named-query ×1
openjpa ×1
oracle ×1
orm ×1
performance ×1
variables ×1