我使用JPA的entitymanager.find(T,pk)来查找记录。这是在成功使用entitymanager.find()的现有应用程序中,但这是使用复合主键的第一个实例。这是实体类:
@Entity
@Table(name = "host_property", schema = "app")
@IdClass(HostPropertyPK.class)
public class HostProperty implements Serializable {
@Id
@Column(name = "host")
private String host_;
@Id
@Column(name = "name")
private String name_;
@Column(name = "value")
private String value_;
private static final long serialVersionUID = 1L;
/**
* Java Persistence requires a no-argument constructor. Private so that only
* JPA may use it.
*/
private HostProperty() {
}
/**
* Gets the associated host.
*
* @return String containing the host
*/
public String getHost() {
return host_;
}
/**
* Gets the property name.
*
* @return String containing the property name
*/
public String getName() {
return name_;
}
/**
* Gets the property value.
*
* @return String containing the property value
*/
public String getValue() {
return value_;
}
/**
* Gets the value as an int.
*
* @return int containing the value parsed as an int
*/
public int getIntValue() {
return Integer.parseInt(value_);
}
}
和主键类:
public class HostPropertyPK implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "host")
private String host_;
@Column(name = "name")
private String name_;
/**
* Java Persistence requires a no-argument constructor. Private so that
* only JPA may use it.
*/
@SuppressWarnings("unused")
private HostPropertyPK() {
}
/**
* Creates a host property primary key.
*
* @param host String containing the host
* @param propertyName String containing the property name
*/
public HostPropertyPK(String host, String propertyName) {
this.host_ = host;
this.name_ = propertyName;
}
/**
* Gets the host of this primary key.
*
* @return String containing the host
*/
public String getHost() {
return host_;
}
/**
* Gets the property name of this primary key.
*
* @return String containing the property name
*/
public String getPropertyName() {
return name_;
}
@Override
public int hashCode() {
int code = 1;
code = 31 * code + (host_ == null ? 0 : host_.hashCode());
code = 31 * code +
(name_ == null ? 0 : name_.hashCode());
return code;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if (!(o instanceof HostPropertyPK)) {
return false;
}
HostPropertyPK other = (HostPropertyPK) o;
if (host_ == null) {
if (other.getHost() != null) {
return false;
}
} else if (!host_.equals(other.getHost())) {
return false;
}
if (name_ == null) {
if (other.getPropertyName() != null) {
return false;
}
} else if (!name_.equals(other.getPropertyName())) {
return false;
}
return true;
}
}
和我查找属性的bean:
@Stateless
@Local(PropertyService.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class PropertyServiceBean implements PropertyService {
@PersistenceContext(unitName="AppPersistence")
private EntityManager entityManager_;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public HostProperty getHostProperty(String host, String propertyName) {
HostPropertyPK hostPropertyPK =
new HostPropertyPK(host, propertyName);
HostProperty prop = entityManager_.find(HostProperty.class, hostPropertyPK);
System.out.println("FOUND HOST PROPERTY : " + prop);
return prop;
}
}
System.out.println处的prop值为null。我可以确认实体管理器不是因为执行到达这一点而且因为我可以使用XRebel捕获基础查询:
select
hostpr0_.host as host623_0_,
hostpr0_.name as name623_0_,
hostpr0_.value as value623_0_
from
app.host_property hostpr0_
where
hostpr0_.host = 'testhost'
and hostpr0_.name = 'testprop'
我已经确认此查询确实返回了一行。但是,Hibernate最终不会返回我的对象,而是返回null!什么可能导致Hibernate能够生成正确的查询,执行它,但不能从中映射对象?