我有两个模特课程:
package com.me.model;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Post {
private Integer id;
private String text;
private Person person;
@Id
@GeneratedValue
@Column(name = "ID")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@ManyToOne(cascade = {CascadeType.ALL})
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return String.format("\nThe id of a post is: %d, written by person %s, containing a text: %s\n", this.id, this.person.toString(), this.text);
}
@Override
public int hashCode() {
int hash = 3;
hash = 89 * hash + Objects.hashCode(this.id);
hash = 89 * hash + Objects.hashCode(this.text);
hash = 89 * hash + Objects.hashCode(this.person);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Post other = (Post) obj;
if (!Objects.equals(this.id, other.id)) {
return false;
}
if (!Objects.equals(this.text, other.text)) {
return false;
}
if (!Objects.equals(this.person, other.person)) {
return false;
}
return true;
}
}
package com.me.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "PERSON")
public class Person implements Serializable {
private Integer id;
private String name;
private String email;
private List<Post> posts;
@OneToMany(mappedBy = "person", fetch = FetchType.EAGER,
cascade = {CascadeType.ALL})
public List<Post> getPosts() {
return posts;
}
public void setPosts(List<Post> posts) {
this.posts = posts;
}
public void addPost(Post post) {
post.setPerson(this);
if (posts == null) {
posts = new ArrayList<Post>();
}
posts.add(post);
}
@Id
@GeneratedValue
@Column(name = "ID")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", email=" + email + ", no of posts: " + this.posts.size() + "]";
}
@Override
public int hashCode() {
int hash = 3;
hash = 17 * hash + Objects.hashCode(this.id);
hash = 17 * hash + Objects.hashCode(this.name);
hash = 17 * hash + Objects.hashCode(this.email);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Person other = (Person) obj;
if (!Objects.equals(this.id, other.id)) {
return false;
}
if (!Objects.equals(this.name, other.name)) {
return false;
}
if (!Objects.equals(this.email, other.email)) {
return false;
}
return true;
}
}
和测试类:
public static final Logger log = Logger.getLogger(Main.class.getName());
public static void main(String[] args) {
log.info("************** BEGINNING PROGRAM **************");
ApplicationContext context = new ClassPathXmlApplicationContext("WEB-INF/spring-config.xml");
PersonService personService = (PersonService) context.getBean("personService");
PostService postService = (PostService) context.getBean("postService");
Person person = new Person();
person.setName("me");
person.setEmail("me@box.com");
Post post = new Post();
String text = "bbbbbbbbbbbbbbbbbbbbbbbbb";
post.setText(text);
Person personFromDB = personService.getPersonFromDB(person.getName(), person.getEmail());
if (personFromDB == null) {
log.info("No person in DB!! ");
person.addPost(post);
personService.addPerson(person);
} else {
log.info("Person " + personFromDB + " is being found in DB!");
// personService.getPersonDao().getEntityManager().detach(personFromDB);
personFromDB.addPost(post);
// personService.addPerson(personFromDB);
personService.updatePerson(personFromDB);
}
List<Person> persons = personService.fetchAllPersons();
log.info("\nThe list of all persons = " + persons);
List<Post> posts = postService.fetchAllPosts();
log.info("\nThe list of all posts = " + posts);
log.info("************** ENDING PROGRAM *****************");
}
andocourse DAO和Service类(由Spring注入的entityManager)。 现在我想从DB更新一个人物对象(在添加另一个帖子之后)。在调试程序时,我可以看到添加到arraylist的新帖子。但是当调用personService.updatePerson(它反过来调用getPersonDao()。getEntityManager()。merge(person);)时没有任何反应!仍然在集合中只有一个项目获得相同的对象 的persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="personPersistenceUnit" transaction-type="RESOURCE_LOCAL" >
<class>com.me.model.Person</class>
<class>com.me.model.Post</class>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
服务类:
import com.me.dao.PersonDao;
import com.me.model.Person;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PersonService {
private PersonDao personDao;
public PersonDao getPersonDao() {
return personDao;
}
@Autowired
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
public void addPerson(Person person) {
getPersonDao().insert(person);
}
public void updatePerson(Person person){
getPersonDao().getEntityManager().merge(person);
}
public List<Person> fetchAllPersons() {
return getPersonDao().selectAll();
}
public boolean isPersonExist(Person person){
if(personDao.getPersonByNameAndEMail(person.getName(), person.getEmail()) != null){
return true;
}
return false;
}
public Person getPersonFromDB(String name, String email){
return personDao.getPersonByNameAndEMail(name, email);
}
}
package com.me.service;
import com.me.dao.PostDao;
import com.me.model.Post;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PostService {
private PostDao personDao;
public PostDao getPostDao() {
return personDao;
}
@Autowired
public void setPostDao(PostDao personDao) {
this.personDao = personDao;
}
public void addPost(Post person) {
getPostDao().insert(person);
}
public void merge(Post post){
getPostDao().getEntityManager().merge(post);
}
public List<Post> fetchAllPosts() {
return getPostDao().selectAll();
}
}
dao classes:
package com.me.dao;
import com.me.model.Person;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Repository("personDao")
@Transactional(propagation = Propagation.REQUIRED)
public class PersonDao {
private static final String SELECT_QUERY = "select p from Person p";
@PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void insert(Person person) {
if(getPersonByNameAndEMail(person.getName(), person.getEmail()) != null){
return;
}
entityManager.persist(person);
}
public List<Person> selectAll() {
Query query = entityManager.createQuery(SELECT_QUERY);
List<Person> persons = (List<Person>) query.getResultList();
return persons;
}
public Person getPersonByNameAndEMail(String name, String email) {
String hql = "select p from Person p where p.name = :theName and p.email = :email";
Query q = entityManager.createQuery(hql);
q.setParameter("theName", name);
q.setParameter("email", email);
q.setMaxResults(1);
Person p;
try{
p = (Person) q.getSingleResult();
}catch(NoResultException e){
p = null;
}
return p;
}
}
package com.me.dao;
import com.me.model.Post;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Repository("potDao")
@Transactional(propagation = Propagation.REQUIRED)
public class PostDao {
private static final String SELECT_QUERY = "select p from Post p";
@PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void insert(Post person) {
entityManager.persist(person);
}
public List<Post> selectAll() {
Query query = entityManager.createQuery(SELECT_QUERY);
List<Post> persons = (List<Post>) query.getResultList();
return persons;
}
}
答案 0 :(得分:0)
我注意到的一个问题与初始化子集合的方式有关。
您没有声明空集合关联:
private List<Post> posts;
但你是这样做的:
private List<Post> posts = new ArrayList();
然后addPost变为:
public void addPost(Post post) {
post.setPerson(this);
posts.add(post);
}
Hibernate将始终使用代理替换发布的ArrayList,这样您就可以确保在访问getPosts()时不需要调用addPost()就可以获得NullPointerException。
Post也是子实体,因为它首先需要Person。您通常不会从子级级联到父级,因此在Post实体中,您可以将级联移除到Parent:
@ManyToOne
public Person getPerson() {
return person;
}
由于this而依赖于equals和hashCode中的id并不是一个好主意。
调用merge并在Parent中进行级联应该将更改传播到数据库。因为双向关联是由addPost设置的。
您的服务方法是否标有@Transactional?