我正在尝试通过Spring和Hibernate填充新创建的数据库模式。
我的@PostConstruct
课程是:
@Component
public class DataInitializer {
@Autowired
private UserService userService;
@Autowired
private UserProfileService userProfileService;
@PostConstruct
public void firstLoad() {
if (!(userProfileService.findAll().size() > 0)) {
System.out.println("persistUserProfiles()");
persistUserProfiles();
} else {
System.out.println("persistUserProfiles() NOT EXECUTED!");
}
if (userService.findAll().size() == 0) {
System.out.println("loadDefaultUser()");
loadDefaultUser();
} else {
System.out.println("loadDefaultUser() NOT EXECUTED!");
}
}
private void loadDefaultUser() {
User user = new User();
user.setSsoId("master");
user.setPassword("$2a$10$Jv/rZ8wa7XiRY8XZ1lpIMeXL/Mol0Eda4XxHM7BE2Ui6BxpLZ95He");
user.setFirstName("HRM");
user.setLastName("Master User");
user.setEmail("email@email");
user.setState(State.ACTIVE.getState());
user.setUserProfiles(loadDefaultUserProfiles());
userService.save(user);
}
private Set<UserProfile> loadDefaultUserProfiles() {
Set<UserProfile> userProfiles = new HashSet<UserProfile>();
userProfiles.add(userProfileService.findByType(UserProfileType.USER.getUserProfileType()));
userProfiles.add(userProfileService.findByType(UserProfileType.ADMIN.getUserProfileType()));
userProfiles.add(userProfileService.findByType(UserProfileType.DBA.getUserProfileType()));
return userProfiles;
}
private void persistUserProfiles() {
UserProfile user = new UserProfile(UserProfileType.USER.getUserProfileType());
userProfileService.save(user);
UserProfile admin = new UserProfile(UserProfileType.ADMIN.getUserProfileType());
userProfileService.save(admin);
UserProfile dba = new UserProfile(UserProfileType.DBA.getUserProfileType());
userProfileService.save(dba);
}
}
但是在运行应用程序服务器时,我得到以下控制台输出和错误:
persistUserProfiles()
loadDefaultUser()
Mar 06, 2016 5:15:25 PM org.springframework.web.context.support.AnnotationConfigWebApplicationContext __refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataInitializer': Invocation of init method failed; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: b.c.m.h.m.UserProfile
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:480)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5075)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5591)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1574)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1564)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
输出明确说明问题出在UserProfile
实体上,该实体定义为:
@Column(name="type", length=15, unique=true, nullable=false)
private String type = UserProfileType.USER.getUserProfileType();
// Constructor used only for initial data loading, not used after
public UserProfile() {
}
// Constructor used only for initial data loading, not used after
public UserProfile(String type) {
super();
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
定义UserProfileType
的枚举是:
USER("USER"),
DBA("DBA"),
ADMIN("ADMIN");
String userProfileType;
private UserProfileType(String userProfileType){
this.userProfileType = userProfileType;
}
public String getUserProfileType(){
return userProfileType;
}
编辑:包含(希望)相关代码
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDao dao;
@Autowired
private PasswordEncoder passwordEncoder;
public void save(User user){
user.setPassword(passwordEncoder.encode(user.getPassword()));
dao.save(user);
}
public void saveOrUpdate(User user) {
// user.setPassword(passwordEncoder.encode(user.getPassword()));
dao.saveOrUpdate(user);
(...)
}
PasswordEncoder是org.springframework.security.crypto.password.PasswordEncoder
。
@Repository("userDao")
public class UserDaoImpl extends AbstractDao<String, User> implements UserDao {
public void save(User user) {
persist(user);
}
public void saveOrUpdate(User user) {
saveOrUpdate(user);
}
(...)
}
处理会话的抽象类:
public abstract class AbstractDao<PK extends Serializable, T> {
private final Class<T> persistentClass;
@SuppressWarnings("unchecked")
public AbstractDao(){
this.persistentClass =(Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
}
@Autowired
private SessionFactory sessionFactory;
protected Session getSession(){
return sessionFactory.getCurrentSession();
}
@SuppressWarnings("unchecked")
public T getByKey(PK key) {
return (T) getSession().get(persistentClass, key);
}
public void persist(T entity) {
getSession().persist(entity);
}
public void saveOrUpdate(T entity) {
getSession().saveOrUpdate(entity);
}
(...)
}
发生了什么事?正在创建所有表,并且填充了user_profile表,但DataInitializer
类在将用户配置文件分配给未被持久化的“主”用户时失败。
我在这里缺少什么?提前谢谢。
答案 0 :(得分:0)
@Repository("userDao")
public class UserDaoImpl extends AbstractDao<String, User> implements UserDao {
public void save(User user) {
persist(user);
}
public void saveOrUpdate(User user) {
saveOrUpdate(user);
}
(...)
}
问题在于我引用自身的方法saveOrUpdate(User user)
内部。
解决方案是:
public void saveOrUpdate(User user) {
super.saveOrUpdate(user);
}