通过 EntityManager 更新数据库
Update DB via EntityManager
我正在开发一个 Spring-MVC 项目,尝试使用 jpa 更新用户的用户名和密码。但我似乎没有取得任何进展。 :D
我检查了 this one 等其他问题,并尝试将他们批准的答案用于我的案例。 las,我的数据库没有任何变化。
到目前为止,我已经尝试了这些方法并且 none 有效:
在设置前使用persist
,按照建议here
按照建议设置后使用 merge
here
正在按照建议手动提交事务here。
不幸的是,这个 class 有很多来自我的数据库周围的外键,我不能安全地删除旧的并添加一个新的 Dept
和新数据。所以,这是我的更新方法 - 当然是在 DAO 级别 - 有人可以在这里建议一种更新用户名和密码的新方法吗?
@Transactional
public Dept updateDept(int depId, String u, String p) {
System.err.println("successfully reached DAO");
Dept dep=entityManager.find(Dept.class,depId);
dep.setUname(u);
dep.setPassword(p);
entityManager.merge(dep);
return entityManager.find(Dept.class,depId); //just to check if update really happened, which did not
}//end of update Dept
编辑:
好的,所以它变得非常复杂。我真的是这个领域的新手,所以我尽量给你提供尽可能多的细节。
这些是我唯一被允许更改的部分,我必须考虑到其他部分(如 JPA 等)的任何其他配置都是由我的高级队友完成的,并且是正确完成的。
这是我的控制器,它应该更新部门经理的用户名和密码,并将用户送回他们的第一页:
@RequestMapping(value="/infoEdit", method=RequestMethod.POST)
public String editManager(HttpServletRequest req, @RequestParam("username") String usernname , @RequestParam("password") String password , Model model) {
int id= (Integer) req.getSession().getAttribute("id");
boolean isUpdated=managerManagerImpl.updateUserPass(id,usernname,password);
System.err.println(isUpdated);
Dept d= managerManagerImpl.getDeptByManagerId(usernname,password);
if (d!=null)
return "themanager/managerFirstPage";
}
在 managerManagerImpl - managerManager 接口的实现中,updateUserPass()
是这样的:
@Override
public Boolean updateUserPass(int id, String usernname, String password) {
Dept dept=managerDAOImpl.getDept(id); // who is this?
Dept possibleDup=managerDAOImpl.getDept(usernname);//maybe this username is taken
Dept newDep=null;
if(possibleDup==null || (possibleDup!=null && possibleDup.getId()==dept.getId())){//username is not taken
System.err.println("going to update it!!");
newDep=managerDAOImpl.updateDept(dept.getId(),usernname,password);
System.err.println("newDep data here : " + newDep.getId() + "// "+newDep.getUname());
Dept newnewDept = managerDAOImpl.getDept(id);
if(newnewDept!=null)
System.err.println("&& newnewDep data here : " + newnewDept.getId() + "// "+newnewDept.getUname());
}
Boolean isUpdated=(null!=newDep && newDep.getId()==dept.getId());
return isUpdated;
}
这是我的整个 managerDAOImpl class:
@Repository
public class TheManagerDAOImpl {
public TheManagerDAOImpl() {
}
@PersistenceContext
public EntityManager entityManager;
@Transactional
public Prof getManager(String usern){
String hql="SELECT p FROM Dept p WHERE p.uname=:username";
Query q= entityManager.createQuery(hql);
q.setParameter("username",usern);
List<Prof> res = (List<Prof>) q.getResultList();
return res == null || res.size() == 0 ? null : res.get(0);
}
@Transactional
public Dept getDept(int managerId) {
String hql= "SELECT d FROM Dept d WHERE d.id=:idHere";
Query q= entityManager.createQuery(hql);
q.setParameter("idHere",managerId);
List<Dept> res = (List<Dept>) q.getResultList();
return res == null || res.size() == 0 ? null : res.get(0);
}
@Transactional
public Dept getDept(String managerId, String managerPass) {
String hql= "SELECT d FROM Dept d WHERE d.uname=:username AND d.password=:pass";
Query q= entityManager.createQuery(hql);
q.setParameter("username",managerId);
q.setParameter("pass",managerPass);
List<Dept> res = (List<Dept>) q.getResultList();
return res == null || res.size() == 0 ? null : res.get(0);
}
@Transactional
public Dept getDept(String managerId) {
String hql= "SELECT d FROM Dept d WHERE d.uname=:username";
Query q= entityManager.createQuery(hql);
q.setParameter("username",managerId);
List<Dept> res = (List<Dept>) q.getResultList();
return res == null || res.size() == 0 ? null : res.get(0);
}
@Transactional
public Dept updateDept(int depId, String u, String p) {
System.err.println("**************************here in dao");
Dept dep=entityManager.find(Dept.class,depId);
dep.setUname(u);
dep.setPassword(p);
entityManager.merge(dep);
return entityManager.find(Dept.class,depId);
}//end of update Dept
}
顺便提一下,那些 System.error 的东西是用来确保它确实调用了这些方法,并且完全不相关。
您正在获取容器管理器持久性上下文,它必须获取 JTA 数据源,但正如我之前从 persistence.xml 中看到的(您已经将其删除),您正在使用资源本地事务(通过指定jdbc 资源)。
正确的配置应该是(对于 XML 配置)
1) 您的数据源
<jdbc:embedded-database id="dataSource" type="H2">
</jdbc:embedded-database>
// or jdbc:initialize-database for non-embedded
2) 您的交易经理
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
2.1) 当您使用注解进行事务划分时,您需要
<tx:annotation-driven transaction-manager="transactionManager" />
3) 你的实体管理器工厂
bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.myPackage"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
我找到了另一种进行更新的方法,我不确定它是否有任何缺点,或者它会在将来破坏我的代码。但既然暂时解决了这个问题,我在这里分享一下。也许会有帮助。
现在我在更新任何现有实体之前清除我的 entityManager
。有点像这样:
@Transactional
public void updateDept(Dept dep,String username, String password) {
entityManager.clear();
dep.setUname(username);
dep.setPassword(password);
entityManager.merge(dep);
}//end of update Dept
令人惊讶的是,它现在工作正常并在数据库上提交更新。
我正在开发一个 Spring-MVC 项目,尝试使用 jpa 更新用户的用户名和密码。但我似乎没有取得任何进展。 :D
我检查了 this one 等其他问题,并尝试将他们批准的答案用于我的案例。 las,我的数据库没有任何变化。
到目前为止,我已经尝试了这些方法并且 none 有效:
在设置前使用
persist
,按照建议here按照建议设置后使用
merge
here正在按照建议手动提交事务here。
不幸的是,这个 class 有很多来自我的数据库周围的外键,我不能安全地删除旧的并添加一个新的 Dept
和新数据。所以,这是我的更新方法 - 当然是在 DAO 级别 - 有人可以在这里建议一种更新用户名和密码的新方法吗?
@Transactional
public Dept updateDept(int depId, String u, String p) {
System.err.println("successfully reached DAO");
Dept dep=entityManager.find(Dept.class,depId);
dep.setUname(u);
dep.setPassword(p);
entityManager.merge(dep);
return entityManager.find(Dept.class,depId); //just to check if update really happened, which did not
}//end of update Dept
编辑: 好的,所以它变得非常复杂。我真的是这个领域的新手,所以我尽量给你提供尽可能多的细节。
这些是我唯一被允许更改的部分,我必须考虑到其他部分(如 JPA 等)的任何其他配置都是由我的高级队友完成的,并且是正确完成的。
这是我的控制器,它应该更新部门经理的用户名和密码,并将用户送回他们的第一页:
@RequestMapping(value="/infoEdit", method=RequestMethod.POST)
public String editManager(HttpServletRequest req, @RequestParam("username") String usernname , @RequestParam("password") String password , Model model) {
int id= (Integer) req.getSession().getAttribute("id");
boolean isUpdated=managerManagerImpl.updateUserPass(id,usernname,password);
System.err.println(isUpdated);
Dept d= managerManagerImpl.getDeptByManagerId(usernname,password);
if (d!=null)
return "themanager/managerFirstPage";
}
在 managerManagerImpl - managerManager 接口的实现中,updateUserPass()
是这样的:
@Override
public Boolean updateUserPass(int id, String usernname, String password) {
Dept dept=managerDAOImpl.getDept(id); // who is this?
Dept possibleDup=managerDAOImpl.getDept(usernname);//maybe this username is taken
Dept newDep=null;
if(possibleDup==null || (possibleDup!=null && possibleDup.getId()==dept.getId())){//username is not taken
System.err.println("going to update it!!");
newDep=managerDAOImpl.updateDept(dept.getId(),usernname,password);
System.err.println("newDep data here : " + newDep.getId() + "// "+newDep.getUname());
Dept newnewDept = managerDAOImpl.getDept(id);
if(newnewDept!=null)
System.err.println("&& newnewDep data here : " + newnewDept.getId() + "// "+newnewDept.getUname());
}
Boolean isUpdated=(null!=newDep && newDep.getId()==dept.getId());
return isUpdated;
}
这是我的整个 managerDAOImpl class:
@Repository
public class TheManagerDAOImpl {
public TheManagerDAOImpl() {
}
@PersistenceContext
public EntityManager entityManager;
@Transactional
public Prof getManager(String usern){
String hql="SELECT p FROM Dept p WHERE p.uname=:username";
Query q= entityManager.createQuery(hql);
q.setParameter("username",usern);
List<Prof> res = (List<Prof>) q.getResultList();
return res == null || res.size() == 0 ? null : res.get(0);
}
@Transactional
public Dept getDept(int managerId) {
String hql= "SELECT d FROM Dept d WHERE d.id=:idHere";
Query q= entityManager.createQuery(hql);
q.setParameter("idHere",managerId);
List<Dept> res = (List<Dept>) q.getResultList();
return res == null || res.size() == 0 ? null : res.get(0);
}
@Transactional
public Dept getDept(String managerId, String managerPass) {
String hql= "SELECT d FROM Dept d WHERE d.uname=:username AND d.password=:pass";
Query q= entityManager.createQuery(hql);
q.setParameter("username",managerId);
q.setParameter("pass",managerPass);
List<Dept> res = (List<Dept>) q.getResultList();
return res == null || res.size() == 0 ? null : res.get(0);
}
@Transactional
public Dept getDept(String managerId) {
String hql= "SELECT d FROM Dept d WHERE d.uname=:username";
Query q= entityManager.createQuery(hql);
q.setParameter("username",managerId);
List<Dept> res = (List<Dept>) q.getResultList();
return res == null || res.size() == 0 ? null : res.get(0);
}
@Transactional
public Dept updateDept(int depId, String u, String p) {
System.err.println("**************************here in dao");
Dept dep=entityManager.find(Dept.class,depId);
dep.setUname(u);
dep.setPassword(p);
entityManager.merge(dep);
return entityManager.find(Dept.class,depId);
}//end of update Dept
}
顺便提一下,那些 System.error 的东西是用来确保它确实调用了这些方法,并且完全不相关。
您正在获取容器管理器持久性上下文,它必须获取 JTA 数据源,但正如我之前从 persistence.xml 中看到的(您已经将其删除),您正在使用资源本地事务(通过指定jdbc 资源)。
正确的配置应该是(对于 XML 配置)
1) 您的数据源
<jdbc:embedded-database id="dataSource" type="H2">
</jdbc:embedded-database>
// or jdbc:initialize-database for non-embedded
2) 您的交易经理
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
2.1) 当您使用注解进行事务划分时,您需要
<tx:annotation-driven transaction-manager="transactionManager" />
3) 你的实体管理器工厂
bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.myPackage"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
我找到了另一种进行更新的方法,我不确定它是否有任何缺点,或者它会在将来破坏我的代码。但既然暂时解决了这个问题,我在这里分享一下。也许会有帮助。
现在我在更新任何现有实体之前清除我的 entityManager
。有点像这样:
@Transactional
public void updateDept(Dept dep,String username, String password) {
entityManager.clear();
dep.setUname(username);
dep.setPassword(password);
entityManager.merge(dep);
}//end of update Dept
令人惊讶的是,它现在工作正常并在数据库上提交更新。