I have two Tables in Mysql sensorlist and sensor_tags, Sensorlist will have the registers from sensors active (Sensor's data and slID to identify the sensor). And Sensor_tags will have the all sensor's tags (from sensors active or not active). Also, sensorlist might have a tag (or slId) was not declarated in Sensor_tags table. I am trying to find a sensor's tag which was not declarated in sensor_tag table. I am using web services with netbeans and always get the error:
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)
My tables:
(This one is in 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;
I generated restful web services from database with Netbeans. From SensorlistFacadeREST.java I implemented a GET method:
@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;
}
In Sensorlist.java, I wrote the Query with the goal for join table sensorlist and sensortags to find all Sensor's tags doesn't exit. Note: If I use st.sensor_id I will get error "The state field path 'st.sensor_id' cannot be resolved to a valid type"
@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")
This is my Sensorlist.java (for check declarations and variables):
//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
}
Don't use ON operator if the relationship is already defined on the entity object, or at least put ON clause only for custom ON filter. The ORM already knows how two entities are linked together using the mapping of the association, so the syntaxically correct query is
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
I'm not sure I understand what you're trying to achieve with this query though If the goal is to find the SensorList having no tag, the query should be
select sl from Sensorlist sl where sl.sensorTagsCollection is empty
Side note: you should really fix your naming. You don't say "Hello mister, what's your mister name?". So why would you say sensorList.getSlName()
instead of simply sensorList.getName()
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With