JPA 2.1 实体,为什么我总是得到实体自身而不是实体的主键?
JPA 2.1 entity, Why I always got the entity self instead of the entity's primary key?
这是对我之前问题的更深入挖掘。
我有一个由 Postgresql 服务器生成的 NetBeans 实体 classes。源代码是:
package com.longz.ozssc.domain;
import javax.persistence.*;
import java.sql.Time;
import java.util.Arrays;
/**
* Created by cidylong on 12/01/2015.
*/
@Entity
@Table(name = "file", schema = "public", catalog = "ozssc")
public class FileEntity {
private String fileId;
private String referId;
private String fileName;
private String fileType;
private byte[] fileData;
private Time createdDatatime;
@Id
@Column(name = "file_id", nullable = false, insertable = true, updatable = true, length = 2147483647)
public String getFileId() {
return fileId;
}
public void setFileId(String fileId) {
this.fileId = fileId;
}
@Basic
@Column(name = "refer_id", nullable = false, insertable = true, updatable = true, length = 2147483647)
public String getReferId() {
return referId;
}
public void setReferId(String referId) {
this.referId = referId;
}
@Basic
@Column(name = "file_name", nullable = false, insertable = true, updatable = true, length = 2147483647)
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
@Basic
@Column(name = "file_type", nullable = true, insertable = true, updatable = true, length = 2147483647)
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
@Basic
@Column(name = "file_data", nullable = false, insertable = true, updatable = true)
public byte[] getFileData() {
return fileData;
}
public void setFileData(byte[] fileData) {
this.fileData = fileData;
}
@Basic
@Column(name = "created_datatime", nullable = false, insertable = true, updatable = true)
public Time getCreatedDatatime() {
return createdDatatime;
}
public void setCreatedDatatime(Time createdDatatime) {
this.createdDatatime = createdDatatime;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FileEntity that = (FileEntity) o;
if (createdDatatime != null ? !createdDatatime.equals(that.createdDatatime) : that.createdDatatime != null)
return false;
if (!Arrays.equals(fileData, that.fileData)) return false;
if (fileId != null ? !fileId.equals(that.fileId) : that.fileId != null) return false;
if (fileName != null ? !fileName.equals(that.fileName) : that.fileName != null) return false;
if (fileType != null ? !fileType.equals(that.fileType) : that.fileType != null) return false;
if (referId != null ? !referId.equals(that.referId) : that.referId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = fileId != null ? fileId.hashCode() : 0;
result = 31 * result + (referId != null ? referId.hashCode() : 0);
result = 31 * result + (fileName != null ? fileName.hashCode() : 0);
result = 31 * result + (fileType != null ? fileType.hashCode() : 0);
result = 31 * result + (fileData != null ? Arrays.hashCode(fileData) : 0);
result = 31 * result + (createdDatatime != null ? createdDatatime.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "com.longz.ozssc.model.FileEntity[ fileId=" + fileId + " ]";
}
}
这是我在项目中使用的非常流行的实体 class。实体主键是fileId,有一组getter/setter对访问实体中的私有属性,如setFileId(String fileId)和getFileId()。
我的远程接口是:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.longz.ozssc.remote;
import com.longz.ozssc.model.FileEntity;
import java.util.List;
import javax.ejb.Remote;
/**
*
* @author cidylong
*/
@Remote
public interface FileEntityFacadeRemote {
void create(FileEntity fileEntity);
void edit(FileEntity fileEntity);
void remove(FileEntity fileEntity);
FileEntity find(Object id);
List<FileEntity> findAll();
List<FileEntity> findRange(int[] range);
int count();
}
我的 EJB 实现是:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.longz.ozssc.ejb;
import com.longz.ozssc.model.FileEntity;
import com.longz.ozssc.remote.FileEntityFacadeRemote;
import com.longz.ozssc.remote.OzsscIdSequenceFacadeRemote;
import com.longz.ozssc.utils.datatime.DateTimeAssistant;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.commons.lang3.StringUtils;
/**
*
* @author cidylong
*/
@Remote(FileEntityFacadeRemote.class)
@Stateless(mappedName="fileEntityFacadeEJB")
public class FileEntityFacade extends AbstractFacade<FileEntity> implements FileEntityFacadeRemote {
@PersistenceContext(unitName = "OzsscJPANBPU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public FileEntityFacade() {
super(FileEntity.class);
}
@EJB
private OzsscIdSequenceFacadeRemote ozsscIdSqFaRemote;
@Override
public List<FileEntity> findAll(){
Query query = em.createNamedQuery("FileEntity.findAllOrderByCreated");
return new LinkedList<FileEntity>(query.getResultList());
/*return super.findAll();*/
}
}
每次调用实体方法 getFileId() 时,
String fileId = (FileEntity)fileEntity.getFileId();
假设我将从实体中得到一个字符串 return,例如:
**FILES20150200013**.
但我的实体总是return:
**com.longz.ozssc.model.FileEntity[ fileId= FILES20150200013 ]**
这个return值正是其他实体方法toString()的打印出来的。也就是说,
当我调用 getFileId() 方法访问实体的主键时,实体 return 对我来说是一个完整的实体值,而不是 return 一个主键。
是我的代码有问题还是实体访问方法有问题?
欢迎任何建议,并非常感谢。
编辑:
当我尝试使用 JPA 2.0 提供的方法访问实体的主键时:
Object identifier =
EntityManagerFactory.getPersistenceUnitUtil().getIdentifier(fileEntity);
我也错了return。烦??
我自己发现了这个问题。
其实。我用 java 客户端包括 WebLogic 客户端库对其进行了测试,我发现它在 Java 客户端中运行良好。
然后,我将相同的测试代码放入 Spring MVC 上下文中,但没有用。 Spring MVC 控制器总是给出错误的 return 值。很好笑。
作为替代解决方案。我使用 Spring 表单对象通过使用 ABN 字符串而不是使用 FirmEntity 来重新组织参数,然后我将 ABN 字符串传递给 EJB,我得到了正确的 return.
这也许可以帮助遇到同样问题的其他人。我认为这个问题是由 Spring Frameworks 的 AOP 功能将错误的字符串绑定到 return 值引起的,在使用此类功能时应该非常小心。
这是对我之前问题的更深入挖掘。
我有一个由 Postgresql 服务器生成的 NetBeans 实体 classes。源代码是:
package com.longz.ozssc.domain;
import javax.persistence.*;
import java.sql.Time;
import java.util.Arrays;
/**
* Created by cidylong on 12/01/2015.
*/
@Entity
@Table(name = "file", schema = "public", catalog = "ozssc")
public class FileEntity {
private String fileId;
private String referId;
private String fileName;
private String fileType;
private byte[] fileData;
private Time createdDatatime;
@Id
@Column(name = "file_id", nullable = false, insertable = true, updatable = true, length = 2147483647)
public String getFileId() {
return fileId;
}
public void setFileId(String fileId) {
this.fileId = fileId;
}
@Basic
@Column(name = "refer_id", nullable = false, insertable = true, updatable = true, length = 2147483647)
public String getReferId() {
return referId;
}
public void setReferId(String referId) {
this.referId = referId;
}
@Basic
@Column(name = "file_name", nullable = false, insertable = true, updatable = true, length = 2147483647)
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
@Basic
@Column(name = "file_type", nullable = true, insertable = true, updatable = true, length = 2147483647)
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
@Basic
@Column(name = "file_data", nullable = false, insertable = true, updatable = true)
public byte[] getFileData() {
return fileData;
}
public void setFileData(byte[] fileData) {
this.fileData = fileData;
}
@Basic
@Column(name = "created_datatime", nullable = false, insertable = true, updatable = true)
public Time getCreatedDatatime() {
return createdDatatime;
}
public void setCreatedDatatime(Time createdDatatime) {
this.createdDatatime = createdDatatime;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FileEntity that = (FileEntity) o;
if (createdDatatime != null ? !createdDatatime.equals(that.createdDatatime) : that.createdDatatime != null)
return false;
if (!Arrays.equals(fileData, that.fileData)) return false;
if (fileId != null ? !fileId.equals(that.fileId) : that.fileId != null) return false;
if (fileName != null ? !fileName.equals(that.fileName) : that.fileName != null) return false;
if (fileType != null ? !fileType.equals(that.fileType) : that.fileType != null) return false;
if (referId != null ? !referId.equals(that.referId) : that.referId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = fileId != null ? fileId.hashCode() : 0;
result = 31 * result + (referId != null ? referId.hashCode() : 0);
result = 31 * result + (fileName != null ? fileName.hashCode() : 0);
result = 31 * result + (fileType != null ? fileType.hashCode() : 0);
result = 31 * result + (fileData != null ? Arrays.hashCode(fileData) : 0);
result = 31 * result + (createdDatatime != null ? createdDatatime.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "com.longz.ozssc.model.FileEntity[ fileId=" + fileId + " ]";
}
}
这是我在项目中使用的非常流行的实体 class。实体主键是fileId,有一组getter/setter对访问实体中的私有属性,如setFileId(String fileId)和getFileId()。
我的远程接口是:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.longz.ozssc.remote;
import com.longz.ozssc.model.FileEntity;
import java.util.List;
import javax.ejb.Remote;
/**
*
* @author cidylong
*/
@Remote
public interface FileEntityFacadeRemote {
void create(FileEntity fileEntity);
void edit(FileEntity fileEntity);
void remove(FileEntity fileEntity);
FileEntity find(Object id);
List<FileEntity> findAll();
List<FileEntity> findRange(int[] range);
int count();
}
我的 EJB 实现是:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.longz.ozssc.ejb;
import com.longz.ozssc.model.FileEntity;
import com.longz.ozssc.remote.FileEntityFacadeRemote;
import com.longz.ozssc.remote.OzsscIdSequenceFacadeRemote;
import com.longz.ozssc.utils.datatime.DateTimeAssistant;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.commons.lang3.StringUtils;
/**
*
* @author cidylong
*/
@Remote(FileEntityFacadeRemote.class)
@Stateless(mappedName="fileEntityFacadeEJB")
public class FileEntityFacade extends AbstractFacade<FileEntity> implements FileEntityFacadeRemote {
@PersistenceContext(unitName = "OzsscJPANBPU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public FileEntityFacade() {
super(FileEntity.class);
}
@EJB
private OzsscIdSequenceFacadeRemote ozsscIdSqFaRemote;
@Override
public List<FileEntity> findAll(){
Query query = em.createNamedQuery("FileEntity.findAllOrderByCreated");
return new LinkedList<FileEntity>(query.getResultList());
/*return super.findAll();*/
}
}
每次调用实体方法 getFileId() 时,
String fileId = (FileEntity)fileEntity.getFileId();
假设我将从实体中得到一个字符串 return,例如:
**FILES20150200013**.
但我的实体总是return:
**com.longz.ozssc.model.FileEntity[ fileId= FILES20150200013 ]**
这个return值正是其他实体方法toString()的打印出来的。也就是说,
当我调用 getFileId() 方法访问实体的主键时,实体 return 对我来说是一个完整的实体值,而不是 return 一个主键。
是我的代码有问题还是实体访问方法有问题?
欢迎任何建议,并非常感谢。
编辑:
当我尝试使用 JPA 2.0 提供的方法访问实体的主键时:
Object identifier =
EntityManagerFactory.getPersistenceUnitUtil().getIdentifier(fileEntity);
我也错了return。烦??
我自己发现了这个问题。
其实。我用 java 客户端包括 WebLogic 客户端库对其进行了测试,我发现它在 Java 客户端中运行良好。
然后,我将相同的测试代码放入 Spring MVC 上下文中,但没有用。 Spring MVC 控制器总是给出错误的 return 值。很好笑。
作为替代解决方案。我使用 Spring 表单对象通过使用 ABN 字符串而不是使用 FirmEntity 来重新组织参数,然后我将 ABN 字符串传递给 EJB,我得到了正确的 return.
这也许可以帮助遇到同样问题的其他人。我认为这个问题是由 Spring Frameworks 的 AOP 功能将错误的字符串绑定到 return 值引起的,在使用此类功能时应该非常小心。