I want to select an entity with specific attributes. Retrieving the whole entity is not an option because of the file
attribute which returns a byte[]
which would slow down the application. However it throws ClassCastException
.
Here is the entity:
@NamedQuery(name = "findAllGarbage", query = "SELECT g.filename, g.description, g.uploadDate FROM Garbage g;")
@Entity
public class Garbage {
@Id
@GeneratedValue
@Column(nullable = false)
private Long id;
@Column(nullable = false)
private String filename;
@Column(nullable = false)
private String fileType;
@Column(nullable = false)
private String uploadDate;
@Column(nullable = false)
private String开发者_如何学Python destroyDate;
@Lob
@Column(nullable = false)
private byte[] file;
@Column(nullable = false)
private String description;
//Getters and Setters...
Here is the EJB for data access. The method findAllGarbage()
is the one that triggers the ClassCastException
.
@Stateless(name = "ejbs/SearchEJB")
public class SearchEJB implements ISearchEJB {
@PersistenceContext
private EntityManager em;
public List<Garbage> findAllGarbage() {
Query query = em.createNamedQuery("findAllGarbage");
List<Garbage> gList = new ArrayList();
for (Object o : query.getResultList()) {
Garbage tmpG = new Garbage();
tmpG.setFilename(((Garbage) o).getFilename());
tmpG.setUploadDate(((Garbage) o).getUploadDate());
tmpG.setDescription(((Garbage) o).getDescription());
gList.add(tmpG);
}
return gList;
}
}
The reason you are getting a ClassCastException is that your getAllGarbage query does not return a collection of Garbage instances. The query is written to specifically return a subset of the values associated with a Garbage instance rather than the full Garbage object. If you debug the method, you will likely notice that query.getResultsList() is returning a collection of Object[]. The Object[] should correspond to the values specified in your named query: filename, description and upload date.
Here is an example of the result usage that should work.
for (Object o : query.getResultList()) {
Object[] cols = (Object[]) o;
Garbage tmpG = new Garbage();
tmpG.setFilename(cols[0]);
tmpG.setDescription(cols[1]);
tmpG.setUploadDate(cols[2]);
gList.add(tmpG);
}
An alternative is to change your native query to
select g from Garbage g
which will result in a full Garbage instance being returned, allowing your original code to execute as expected.
On a side note, I recommending against performing a class cast for every access to the Garbage instance as you are doing in your sample code. This technique adds uneeded overhead to the application and makes the code harder to maintain in the long run. If you are going to use a casted object more than once, create a variable to store the casted instance and reuse it.
If you make the file information lazy, then it won't slow down the application. that is a common strategy when you have a field (or fields) which contains large data.
精彩评论