【问题标题】:Update DB via EntityManager通过 EntityManager 更新数据库
【发布时间】:2017-06-23 13:22:31
【问题描述】:

我正在开发一个 Spring-MVC 项目,尝试使用 jpa 更新用户的用户名和密码。但我似乎没有任何进展。 :D

我检查了其他问题,例如 this one,并尝试将他们批准的答案用于我的案例。唉,我的数据库没有任何变化。

到目前为止,我已经尝试了这些方法,但都没有奏效:

  1. 在设置前使用persist,建议here

  2. 按照建议设置后使用merge here

  3. 按照here的建议手动提交事务。

不幸的是,这个类有很多来自我的数据库周围的外键,我不能安全地删除旧的并添加一个新的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 课程:

@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 东西是用来确保它实际调用这些方法的,并且完全不相关。

【问题讨论】:

  • 你能分享你的持久化配置吗?
  • entityManager.merge() 完全没用:您已经有一个托管实体。并且返回严格等价于return dep。我的猜测是问题在于您如何获取实体管理器或包含此方法的类的实例。或在您的弹簧配置中。您需要向我们展示更多您的代码和配置。
  • 可能你在spring中的JPA配置配置不正确。
  • @DmitrySenkovich 我不是这些东西的专家,你能解释一下我应该在我的问题中添加哪个文件吗?据我所知,这里有一个持久性上下文,我刚刚提到它来启动我的 entityManager。抱歉:">
  • @Sarah Amini 我需要你设置持久性。如果您使用 Spring 或在 java 配置中,我可能会在 Spring xml 配置文件中找到。 entityManagerFactory是怎么设置的?

标签: spring-mvc jpa dao entitymanager


【解决方案1】:

您正在获取容器管理器持久性上下文,它必须获取 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>

【讨论】:

  • 抱歉,我认为该文件无关紧要。我得到了一个简短的解决方案,尝试了一下,它奏效了。不知道这是否是一个好的。但是由于它解决了我的问题,所以我没有完成您建议的所有这些更改。但我非常感谢您的帮助,并进行所有这些更改以防止出现进一步的问题。非常感谢!
【解决方案2】:

我找到了另一种进行更新的方法,我不确定它是否有任何缺点,或者它会在将来破坏我的代码。但是由于它现在解决了这个问题,我在这里分享它。也许会有所帮助。

现在我在更新任何现有实体之前清除我的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

令人惊讶的是,它现在可以正常工作并在 DB 上提交更新。

【讨论】:

    猜你喜欢
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-12
    • 2019-09-05
    • 2016-02-12
    • 1970-01-01
    相关资源
    最近更新 更多