有两个实体类:
通知和用户,需求是发送通知给各个用户,用户可以看到发来的所有通知,那么就是一个双向n-n的关系,看我下边的两个实体类:
/**
* @Project: middleware
* @Title: Notify.java
* @Package com.richsoft.middleware.domain
* @Description: TODO
* @author dsun Email:[email protected]
* Blog:http://blog.csdn.net/dsundsun/article/
* QQ:349466315
* @date 2014年2月26日 下午4:07:37
* @Copyright: 2014
* @version V1.0
*/
package com.richsoft.middleware.domain;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
/**
* @ClassName Notify
* @Description TODO
* @author dsun Email:[email protected]
* Blog:http://blog.csdn.net/dsundsun/article/ QQ:349466315
* @date 2014年2月26日 下午4:07:37
*/
@Entity(name = "tb_notify")
public class Notify implements Serializable {
/**
* @Fields serialVersionUID : 序列化
*/
private static final long serialVersionUID = -1274705480010201155L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;// 标示符
@Column(length = 255)
public String content;// 通知内容
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "notify_user",
joinColumns = { @JoinColumn(name = "uid", referencedColumnName = "id") },
inverseJoinColumns = { @JoinColumn(name = "nid", referencedColumnName = "id") })
private Set users = new HashSet();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Set getUsers() {
return users;
}
public void setUsers(Set users) {
this.users = users;
}
@Override
public String toString() {
return "Notify [id=" + id + ", content=" + content + ", users=" + users
+ "]";
}
}
package com.richsoft.middleware.domain;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
/**
* @ClassName User
* @Description 用户登陆注册操作的基本信息
* @author dsun Email:[email protected]
* Blog:http://blog.csdn.net/dsundsun/article/
* QQ:349466315
* @date 2014年2月7日 上午8:41:34
*/
@Entity(name="tb_user")
public class User implements Serializable {
/**
* @Fields serialVersionUID : 序列化
*/
private static final long serialVersionUID = -7275682073812567790L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id ; //标示符
@Column(nullable=false,length=255)
private String email; //用户名(邮箱)
@Column(nullable=false,length=255)
private String password ;//密码
@Column(length=255)
private String address;//住址
@Column(length=255)
private String realname;//用户真实姓名
@Column(length=255)
private String skills;//熟悉的技能
@Column(length=255)
private String icon;//用户头像
@Column(length=50)
private String theme = "blue";//网站主题模板样式
@Column(length=255)
private String shortname;//名字简写
@OneToMany(fetch=FetchType.LAZY,mappedBy="user")
private Set dbconfigs = new HashSet();
@ManyToMany(mappedBy="users", fetch=FetchType.LAZY)
private Set notifys = new HashSet();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getRealname() {
return realname;
}
public void setRealname(String realname) {
this.realname = realname;
}
public String getSkills() {
return skills;
}
public void setSkills(String skills) {
this.skills = skills;
}
public Set getDbconfigs() {
return dbconfigs;
}
public void setDbconfigs(Set dbconfigs) {
this.dbconfigs = dbconfigs;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getTheme() {
return theme;
}
public void setTheme(String theme) {
this.theme = theme;
}
public String getShortname() {
return shortname;
}
public void setShortname(String shortname) {
this.shortname = shortname;
}
public Set getNotifys() {
return notifys;
}
public void setNotifys(Set notifys) {
this.notifys = notifys;
}
@Override
public String toString() {
return "User [id=" + id + ", email=" + email + ", password=" + password
+ ", address=" + address + ", realname=" + realname
+ ", skills=" + skills + ", icon=" + icon + ", theme=" + theme
+ ", shortname=" + shortname + ", dbconfigs=" + dbconfigs
+ ", notifys=" + notifys + "]";
}
}
这两个配置好多对多以后,在用户表中的notifys使用mappedBy,将控制方交给通知实体控制,这时候,进行业务逻辑操作,如下:
@Override
public void addNotify(String notifyContent,String[] uid) {
Set userSet = new HashSet();
User user = null;
for (String string : uid) {
try{
user = userDao.findOne(Long.valueOf(string));
}catch(Exception e){
continue;
}
userSet.add(user);
}
Notify notify = new Notify();
notify.setContent(notifyContent);
notify.setUsers(userSet);
notifyDao.save(notify);
}
严重: Servlet.service() for servlet springmvc threw exception
org.hibernate.PersistentObjectException: detached entity passed to persist: com.richsoft.middleware.domain.User
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:797)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:790)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:97)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:352)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:295)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:381)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:321)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:298)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:460)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:294)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:780)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:257)
at $Proxy26.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:358)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:358)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at $Proxy27.save(Unknown Source)
at com.richsoft.middleware.core.service.impl.NotifyServiceImpl.addNotify(NotifyServiceImpl.java:66)
at com.richsoft.middleware.web.controller.NotifyController.sendNotify(NotifyController.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)
@ManyToMany(cascade = CascadeType.DETACH, fetch = FetchType.EAGER)
@JoinTable(name = "notify_user",
joinColumns = { @JoinColumn(name = "uid", referencedColumnName = "id") },
inverseJoinColumns = { @JoinColumn(name = "nid", referencedColumnName = "id") })
private Set users = new HashSet();
官方文档:
ALL
public static final CascadeType ALL
Cascade all operations
PERSIST
public static final CascadeType PERSIST
Cascade persist operation
MERGE
public static final CascadeType MERGE
Cascade merge operation
REMOVE
public static final CascadeType REMOVE
Cascade remove operation
REFRESH
public static final CascadeType REFRESH
Cascade refresh operation
DETACH
public static final CascadeType DETACH
Cascade detach operation
Since:
Java Persistence 2.0
DETACH 若父实体从持久上下中游离(detached)出来,则关联实体也会游离。
MERGE 若父实体合并(merge)到持久化上下文,那关联实体也会被合并。
PERSIST 若父实体被持久化(persist)到持久化上下文,那关联实体也会被持久化。
REFRESH 若当前持久化上下文中父实体刷新(refresh)了,则关联实体也会刷新。
REMOVE 若复试题从当前持久化上下文中移除(remove),则关联实体也会移除。