我在Mysql的sensorlist和sensor_tags中有两个表,Sensorlist将激活来自传感器的寄存器(Sensor的数据和slID来识别传感器)。并且Sensor_tags将具有所有传感器的标签(来自 Activity 的或未 Activity 的传感器)。同样,sensorlist可能具有未在Sensor_tags表中声明的标签(或slId)。我试图找到在sensor_tag表中未声明的传感器标签。我在netbeans中使用Web服务,并且总是收到错误消息:
Advertencia: EJB5184:A system exception occurred during an invocation on EJB SensorlistFacadeREST, method: public java.util.List entities.service.SensorlistFacadeREST.createSensorList()
Advertencia: javax.ejb.EJBException
Caused by: Exception [EclipseLink-6076] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.QueryException
Exception Description: Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Mapping: [org.eclipse.persistence.mappings.DirectToFieldMapping[slId-->sensorlist.slId]]
Expression: [
Query Key slId
Base entities.Sensorlist]
Query: ReportQuery(name="Sensorlist.CreateSensorList" referenceClass=Sensorlist jpql="SELECT sl.slId, sl.slName1, sl.slName2, sl.slName3, sl.slInsertTimestamp, sl.slGMTOffset, sl.slActualTimestamp, sl.slActualValue, sl.slActualStatus FROM Sensorlist sl LEFT OUTER JOIN SensorTags st ON sl.slId = st.sensorId WHERE st.sensorId IS NULL")
at org.eclipse.persistence.exceptions.QueryException.unsupportedMappingForObjectComparison(QueryException.java:1164)
我的桌子:
(这是在SQL中:)
TABLE`sensorlist` (
`slId` INT(11) NOT NULL AUTO_INCREMENT,
`slName1` VARCHAR(255) NULL DEFAULT NULL,
`slName2` VARCHAR(255) NULL DEFAULT NULL,
`slName3` VARCHAR(255) NULL DEFAULT NULL,
`slInsertTimestamp` DATETIME NULL DEFAULT NULL,
`slActualTimestamp` DATETIME NULL DEFAULT NULL,
`slGMTOffset` INT(11) NULL DEFAULT NULL,
`slActualValue` DOUBLE NULL DEFAULT NULL,
`slActualStatus` INT(11) NULL DEFAULT NULL,
INDEX `sensorlist_status_idx` (`slActualStatus` ASC),
PRIMARY KEY (`slId`),
CONSTRAINT `sensorlist_status`
FOREIGN KEY (`slActualStatus`)
REFERENCES `factoryecomation_v2`.`status` (`stId`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
AUTO_INCREMENT = 21
DEFAULT CHARACTER SET = utf8;
TABLE `sensor_tags` (
`sensor_tag` VARCHAR(45) NOT NULL,
`id_sensor_catalog` INT(11) NULL DEFAULT NULL,
`comm_device_tag` VARCHAR(45) NOT NULL,
`max_value` FLOAT NULL DEFAULT NULL,
`min_value` FLOAT NULL DEFAULT NULL,
`id_measurement_unit` INT(11) NULL DEFAULT NULL,
`sensor_id` INT(11) NULL DEFAULT NULL,
`active` BIT(1) NOT NULL DEFAULT b'1',
`insert_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_update_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`sensor_tag`),
INDEX `fk_sensor_tags_sensorlist1_idx` (`sensor_id` ASC),
CONSTRAINT `fk_sensor_tags_sensorlist1`
FOREIGN KEY (`sensor_id`)
REFERENCES `factory`.`sensorlist` (`slId`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
我使用Netbeans从数据库生成了宁静的Web服务。从SensorlistFacadeREST.java中,我实现了GET方法:
@GET
@Path("operation/createSensorList")
@Produces({"application/xml", "application/json"})
public List<Sensorlist> createSensorList(){
System.out.print("Prueba 1");
Query query = em.createNamedQuery("Sensorlist.CreateSensorList");
System.out.print("Prueba 2");
List<Sensorlist> services = query.getResultList();
System.out.print("Prueba 3");
return services;
}
在Sensorlist.java中,我编写了查询,目标是联接表sensorlist和sensortags以查找所有Sensor的标签没有退出。注意:如果使用st.sensor_id,则会收到错误“状态字段路径'st.sensor_id'无法解析为有效类型”
@NamedQuery(name = "Sensorlist.CreateSensorList", query ="SELECT sl.slId, sl.slName1, sl.slName2, sl.slName3, sl.slInsertTimestamp, sl.slGMTOffset, sl.slActualTimestamp, sl.slActualValue, sl.slActualStatus FROM Sensorlist sl LEFT OUTER JOIN SensorTags st ON sl.slId = st.sensorId WHERE st.sensorId IS NULL")
这是我的Sensorlist.java(用于检查声明和变量):
//imports
@Entity
@Table(name = "sensorlist")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Sensorlist.findAll", query = "SELECT s FROM Sensorlist s"),
@NamedQuery(name = "Sensorlist.findBySlId", query = "SELECT s FROM Sensorlist s WHERE s.slId = :slId"),
@NamedQuery(name = "Sensorlist.findBySlName1", query = "SELECT s FROM Sensorlist s WHERE s.slName1 = :slName1"),
@NamedQuery(name = "Sensorlist.findBySlName2", query = "SELECT s FROM Sensorlist s WHERE s.slName2 = :slName2"),
@NamedQuery(name = "Sensorlist.findBySlName3", query = "SELECT s FROM Sensorlist s WHERE s.slName3 = :slName3"),
@NamedQuery(name = "Sensorlist.findBySlInsertTimestamp", query = "SELECT s FROM Sensorlist s WHERE s.slInsertTimestamp = :slInsertTimestamp"),
@NamedQuery(name = "Sensorlist.findBySlActualTimestamp", query = "SELECT s FROM Sensorlist s WHERE s.slActualTimestamp = :slActualTimestamp"),
@NamedQuery(name = "Sensorlist.findBySlGMTOffset", query = "SELECT s FROM Sensorlist s WHERE s.slGMTOffset = :slGMTOffset"),
@NamedQuery(name = "Sensorlist.findBySlActualValue", query = "SELECT s FROM Sensorlist s WHERE s.slActualValue = :slActualValue"),
@NamedQuery(name = "Sensorlist.CreateSensorList", query ="SELECT sl.slId, sl.slName1, sl.slName2, sl.slName3, sl.slInsertTimestamp, sl.slGMTOffset, sl.slActualTimestamp, sl.slActualValue, sl.slActualStatus FROM Sensorlist sl LEFT OUTER JOIN SensorTags st ON sl.slId = st.sensorId WHERE st.sensorId IS NULL")})
public class Sensorlist implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "slId")
private Integer slId;
@Size(max = 255)
@Column(name = "slName1")
private String slName1;
@Size(max = 255)
@Column(name = "slName2")
private String slName2;
@Size(max = 255)
@Column(name = "slName3")
private String slName3;
@Column(name = "slInsertTimestamp")
@Temporal(TemporalType.TIMESTAMP)
private Date slInsertTimestamp;
@Column(name = "slActualTimestamp")
@Temporal(TemporalType.TIMESTAMP)
private Date slActualTimestamp;
@Column(name = "slGMTOffset")
private Integer slGMTOffset;
// @Max(value=?) @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
@Column(name = "slActualValue")
private Double slActualValue;
@OneToMany(mappedBy = "saSensorId")
private Collection<Sensorarchive> sensorarchiveCollection;
@OneToMany(mappedBy = "sensorId")
private Collection<SensorTags> sensorTagsCollection;
@JoinColumn(name = "slActualStatus", referencedColumnName = "stId")
@ManyToOne
private Status slActualStatus;
//more stuffs
}
最佳答案
如果实体对象上已经定义了关系,则不要使用ON运算符,或者至少仅对自定义ON过滤器使用put子句。 ORM已经知道如何使用关联映射将两个实体链接在一起,因此语法上正确的查询是
select sl from Sensorlist sl // why select each and every field instead of selecting the entity?
left outer join sl.sensorTagsCollection st
where st.sensorId is null
我不确定我是否理解您要通过此查询实现的目标,但是如果目标是找到没有标签的SensorList,则查询应为
select sl from Sensorlist sl where sl.sensorTagsCollection is empty
旁注:您应该确实修正命名。您不会说“您好先生,您的先生叫什么名字?”。那么,为什么要说
sensorList.getSlName()
而不是简单的sensorList.getName()
?