Father.java
@Entity
@Table(name = ClinicManagementVariableUtils.TABLE_NAME_FOR_FATHER)
@JsonInclude(Include.NON_EMPTY)
@NamedQueries({
@NamedQuery(name = "father.findAll", query = "SELECT f FROM Father f")
})
@NamedEntityGraphs({
@NamedEntityGraph(
name = "graph.father.setOfChildrens",
attributeNodes = @NamedAttributeNode(value = "setOfChildrens")),
})
})
public class Father {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "fatherId", nullable = false, insertable = false, updatable = false)
private String id;
@Column(name = "name", columnDefinition = "varchar(50)")
private String name;
@Column(name = "firstName", columnDefinition = "varchar(50)")
private String firstName;
@Column(name = "lastName", columnDefinition = "varchar(50)")
private String lastName;
@Column(name = "degree", columnDefinition = "varchar(50)")
private String degree;
@OneToOne(mappedBy = "father")
@JsonIgnore
private Mother mother;
@OneToMany(mappedBy = "father") // children
private Set<Children> setOfChildrens;
getter()
setter()
}
Children.java
@Entity
@Table(name = ClinicManagementVariableUtils.TABLE_NAME_FOR_CHILDREN)
@JsonInclude(Include.NON_EMPTY)
public class Children {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "childrenId", nullable = false, insertable = false, updatable = false)
private String id;
@Column(name = "name", columnDefinition = "varchar(50)", nullable = false)
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnore
private Father father;
getter()
setter()
}
Mother.java
@Entity
@Table(name = ClinicManagementVariableUtils.TABLE_NAME_FOR_MOTHER)
@JsonInclude(Include.NON_EMPTY)
public class Mother {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "motherId", nullable = false, insertable = false, updatable = false)
private String id;
@Column(name = "name", columnDefinition = "varchar(50)", nullable = false)
private String name;
@OneToOne
@JoinColumn(name = "fatherId")
private Father father;
getter()
setter()
}
FatherDao.java
public interface FatherDao extends GenericModelDao<Father> {
// Note : Return type is Mother instead of Father
public List<Mother> getFathersUsingNativeQueryAndEntityGraph();
}
FatherDaoImpl.java
@Named
public class FatherDaoImpl extends GenericModelDaoImpl<Father> implements FatherDao {
@PersistenceContext
EntityManager entityManager;
@Override
public List<Mother> getFathersUsingNativeQueryAndEntityGraph() {
EntityGraph graph = entityManager.getEntityGraph("graph.father.setOfChilrensAndAddresses");
List<Mother> list = entityManager.createNamedQuery("father.findAll").setHint("javax.persistence.fetchgraph", graph)
.getResultList();
return list;
}
}
FatherService.java
public interface FatherService {
// Note : Return type is Mother instead of Father
public List<Mother> getFathersUsingNativeQueryAndEntityGraph();
}
FatherServiceImpl.java
@Named
public class FatherServiceImpl implements FatherService {
@Inject
private FatherDao fatherDao;
@Override
public List<Mother> getFathersUsingNativeQueryAndEntityGraph() {
return fatherDao.getFathersUsingNativeQueryAndEntityGraph();
}
}
FatherController.java
@Controller
public class FatherController {
private static final Logger LOGGER = LoggerFactory.getLogger(FatherController.class);
@CrossOrigin
@RequestMapping(value = "/getFathersUsingNativeQueryAndEntityGraph", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<Mother> getFathersUsingNativeQueryAndEntityGraph() {
List<Mother> list = new ArrayList<>();
try {
// Note : now list of father object is return as list of mother but it working..
list = fatherService.getFathersUsingNativeQueryAndEntityGraph();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
在Father.java
中,有两种注释:
现在在DAO层中,我使用getFathersUsingNativeQueryAndEntityGraph()
方法中的图形查询执行本机查询,该方法将返回父亲列表。
但是当我在List<Mother>
中抓取它时,即使Father.java
中不存在这些字段,它也会返回Mother.java
中的所有字段。
的疑问:
如果它返回Father.java
的所有字段,那么它如何在Mother.java
中返回响应?
答案 0 :(得分:2)
<强> 1。由于您在任何地方都没有类型检查,因此该代码将始终进行编译。
<强> 2。只要您从未专门作为Mother
对象访问该列表中的对象,您的代码就会运行。
如果在没有类参数的情况下使用createNamedQuery
,则会创建一个无类型的Query
对象,该对象会返回原始列表以及JPA返回的任何对象。
在您的代码中,此列表将包含Father
个对象,因为这就是您要求的内容。
写List<Mother> list = ...
是错误的,但你的编译器并不知道这一点。由于类型参数仅在编译时检查,因此此代码将运行,并且在运行时 list
期间将是包含Father
个对象的通用列表。
这里你应该得到一个编译器警告关于将该通用列表转换为List<Mother>
,因为编译器不能保证这是正确的。听取这样的警告,他们是有原因的。
只有当你这样做时:
Mother mother = list.get(0);
你会得到运行时错误,特别是ClassCastException
。但是,您的编译器不会抱怨此,因为它认为您的列表将包含Mother
个对象,因为您在上面撒谎。
修复您的代码
您应该使用TypedQuery
代替,将您期望的课程传递给createNamedQuery
:
entityManager.createNamedQuery("father.findAll", Father.class)
这将在编译时期间强制执行正确的类型,因此执行List<Mother> list = ...
将不再编译。