【问题标题】:Data access layer with Spring DAO and Hibernate.Problems带有 Spring DAO 和 Hibernate.Problems 的数据访问层
【发布时间】:2009-07-10 15:17:46
【问题描述】:

大家好,这是我在 spring 和 hibernate 中的第一个应用程序。所以请多多指教一些愚蠢的问题 :)。 我在 netbeans 6.7 中创建了一个简单的 java 应用程序。 这是我的 daos 接口 用户DAO

package Dao;

import Entities.Users;

public interface UsersDAO {
    public Long GetIdByUsernameAndPasswor(String username, String password);
    public Users GetAllByID(Long id);
    public boolean Create(Users user);
    public boolean Delete(Users user);
    public boolean Edit(Users user);
}

和 ContactDAO

package Dao;

import Entities.Contacts;
import java.util.List;

public interface ContactsDAO {
    public List GetAll();
    public Contacts GetAllById(Long Id);
    public boolean Create(Contacts contact);
    public boolean Delete(Contacts contact);
    public boolean Edit(Contacts contact);
}

及其实现

package Dao.DaoImpl;

import Dao.UsersDAO;
import Entities.Users;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class UserDAOImpl  extends HibernateDaoSupport implements UsersDAO {
    //    private SessionFactory sessionFactory;
    public UserDAOImpl(){}

    public Long GetIdByUsernameAndPasswor(String username, String password)
    {
        try
        {
             return DataAccessUtils.longResult(getHibernateTemplate().find("select u.user_id from Users u where u.username=? and u.password", new Object[] {username, password}) );
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            return Long.parseLong("0");
        }
    }

    public Users GetAllByID(Long id) {
       try
       {
           return (Users) getHibernateTemplate().get(Users.class, id);
       }
       catch(Exception ex)
       {
            ex.printStackTrace();
            return new Users();
       }
    }

    public boolean Create(Users user) {
       try
       {
            getHibernateTemplate().save(user);
            return true;
       }
       catch(Exception ex)
       {
           ex.printStackTrace();
           return false;
       }
    }

    public boolean Delete(Users user) {
       try
       {
           getHibernateTemplate().delete(user);
           return true;
       }
       catch(Exception ex)
       {
           ex.printStackTrace();
           return false;
       }
    }

    public boolean Edit(Users user) {
       try
       {
           getHibernateTemplate().saveOrUpdate(user);
           return true;
       }
       catch(Exception ex)
       {
           ex.printStackTrace();
           return false;
       }
      }
    }

package Dao.DaoImpl;

import Dao.ContactsDAO;
import Entities.Contacts;
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class ContactsDAOImpl extends HibernateDaoSupport implements ContactsDAO{
    public ContactsDAOImpl(){}

    public List GetAll() {
        try
        {
            return getHibernateTemplate().find("from Contacts");
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            return null;
        }
    }

    public Contacts GetAllById(Long Id) {
      return (Contacts) getHibernateTemplate().get(Contacts.class, Id);
    }

    public boolean Create(Contacts contact) {
        try
        {
            getHibernateTemplate().save(contact);
            return true;
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            return false;
        }
    }

    public boolean Delete(Contacts contact) {

        try
        {
            getHibernateTemplate().delete(contact);
            return true;
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            return false;
        }
    }

    public boolean Edit(Contacts contact) {

        try
        {
            getHibernateTemplate().saveOrUpdate(contact);
            return true;
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            return false;
         }
        }
    }

我的spring配置文件在Resources.so文件夹下,一般路径是Resouces/contactmanagement.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />

    <property name="url" value="jdbc:mysql://localhost:3306/ContactsMan" />
    <property name="username" value="root" />
    <property name="password" value="letmein" />
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.SessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResouces">
        <list>
            <value>Resources/users.hbm.xml</value>
            <value>Resources/contacts.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
        </props>
    </property>
</bean>
<bean id="usersdao" class="Dao.DaoImpl.UserDAOImpl">
    <property name="sessionFactory" ref="sessionFactory">
</bean>
<bean id="contactsdao" class="Dao.DaoImpl.ContactDAOImpl">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>

映射文件在同一个资源文件夹 users.hbm.xml contacts.hbm.xml 下

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="Entities.Contacts" table="contacts">
            <id name="contact_id">
                    <generator class="increment"/>
            </id>
            <many-to-one cascade="" class="Users" name="user"/>
            <property name="firstname" />
            <property name="lasstname" />
            <property name="cellphone1" />
            <property name="cellphone2" />
            <property name="telephone" />
            <property name="email" />
        </class>
    </hibernate-mapping>

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="Entities.Users" table="users">
            <id name="users_id">
                <generator class="increment"/>
            </id>
            <bag name="contacts" inverse="true" lazy="true">
                <key column="user_id"/>
                <one-to-many class="Contacts"/>
            </bag>

            <property name="username"/>
            <property name="passsword"/>
            <property name="city"/>
            <property name="country"/>

        </class>
    </hibernate-mapping>

这终于是我的主要课程了

package main;
import Dao.UsersDAO;
import Entities.Users;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext
public class contactmanagement {

public static void main(String[] args)
{
    ApplicationContext ctx = new ClassPathXmlApplicationContext("Resources/contactmanagement.xml");
    UsersDAO usersdao = (UsersDAO) ctx.getBean("usersdao");
    Users user = new Users();
    user.setUsername("me");
    user.setPassword("mypass");
    user.setCity("somecity");
    user.setCountry("somecountry");

    usersdao.Create(user);
    System.out.println("created");
 }

当我运行它时,它说要给出一个摘要“没有定义名为 'usersdao' 的 bean” 请问我做错了什么? 这是关于 DAO 实现类的另一个问题。我应该设置属性 setSessionFactory 吗?还是 spring 通过 getHibernateTemplate() 处理所有事情? 请让我通过这个。感谢阅读。我知道它很长;)

【问题讨论】:

  • 您的格式一团糟。我什至不会尝试阅读。
  • 修正格式,我们来看看。

标签: java hibernate spring jakarta-ee


【解决方案1】:

我可以建议改用 Spring Annotations 吗?我并不是要让你先搞清楚另一件事,但是一旦你掌握了窍门,就比让所有配置和映射文件一起工作要容易得多。

这里的第 3.11 和 3.12 章中有一些非常详细的信息: Spring Documentation Chapter 3. The IoC container 但它基本上归结为:

  • 您可以使用@Repository(或@Service)注释要定义为bean 的DAO 类。
  • 无论你需要在哪里使用这样的 DAO,你都可以在你的类中声明一个字段:@Autowired MyExampleDAO myDao; (这些类本身也应该用 @Service 注释才能工作(或者还有其他方法吗?))
  • 配置 Spring 以查找这些注解,它会做到这一点,以便在您需要时始终为您的 bean 提供一个实现。

举个例子,我的整个spring配置是这样的:

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <context:component-scan base-package="org.path.to.your.base.package" />

    <!-- Transaction Manager -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <tx:annotation-driven />

    <!-- Session Factory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="configLocation" value="hibernate.cfg.xml" />
    </bean>
</beans>

一个示例 DAO 如下所示:

@Repository
public class UserHibDAO extends GenericHibernateDAO<HopeUser> implements UserDAO {
    public IUser findByName(String name) {
        return (User) createCriteria(Restrictions.naturalId().set("name", name)).uniqueResult();
    }
}

使用这个 DAO 看起来像这样:

@Service
public class Installer {
    private static final Logger log = Logger.getLogger(Installer.class);

    public static void main(String[] args) throws Exception {
        Installer inst = (Installer) SpringUtil.getContext().getBean("installer");
        inst. storeUsers();
        log.info("Done");
    }

@Autowired
private UserDAO userdao;

@Transactional
public void storeUsers() {
    userdao.makePersistent(new User("Tim"));

    log.info("Users stored");
}
}

请特别注意查看最后一个代码示例中的 main 方法:这是您必须使用的,而不是 new Installer() 才能使自动装配工作。

无论如何,希望这个示例对您有所帮助,我意识到它不是您问题的直接答案,而是手头问题的替代解决方案。

【讨论】:

  • 感谢您为帮助我所做的努力。我认为通过少量阅读我就达到了某种程度。还有另一件事让我感到不安。我是否应该创建 sessionFactory 属性。我正在使用的书不使用它,但在网上我可以看到它。除了在我尝试创建一个时,我只能访问 org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean 但在书中它使用 org.springframework.orm.hibernate3.annotation .SessionFactoryBean.所以我有点困惑。谢谢
  • ASFB 和 SFB 的区别在于第一个用于 Hibernate Annotations,第二个用于 Hibernate Mapping 文件。我看到您仍在使用映射文件,因此您可以使用 SessionFactoryBean,但我相信 AnnotationSessionFactoryBean 也应该能够处理映射文件。在这种情况下,使用 ASFB 也应该没问题。
  • 至于您的第二个问题:如果您在 spring 配置文件中包含 行,然后你可以声明一个字段“@Autowired private SessionFactory sessionFactory;”在您的 UserDAOImpl 中。如果然后在“public class UserDAOImpl”上方的行中添加注释“@Repository”,Spring 应该会神奇地使 SessionFactory 可供您使用..
【解决方案2】:

首先,您需要在两个 DAO 中创建 sessionFactory 的 setter,因为您必须在 contactmanagement.xml 的两个 bean(UserDAO 和 ContectDAO)中注入 sessionfactory。

另一种替代方式是,您可以在 DAO 中使用 HibernateTemplete。

例如:

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate.Hibernate Template">
      <property name="sessionFactory"><ref bean="sessionFactory"/></property> 
</bean>

然后在两个 (DAO) 中创建 hibernateTemplate 的设置器。 之后你可以使用 hibernateTemplate.save(); hibernateTemplate.saveOrUpdate(); hibernateTemplate.delete(); hibernateTemplate.find();
等等……

【讨论】:

    【解决方案3】:

    你的格式很糟糕,所以我还没有真正解决你的整个问题,但我确实注意到你没有在这里关闭你的 property 标签:

    <bean id="usersdao" class="Dao.DaoImpl.UserDAOImpl">
        <property name="sessionFactory" ref="sessionFactory">
    </bean>
    

    应该是:

    <bean id="usersdao" class="Dao.DaoImpl.UserDAOImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    

    【讨论】:

    • 您是否尝试过修复您的 Spring 配置文件?问题还在吗?
    【解决方案4】:

    一些笔记,虽然我没有回答你的问题 -

    你没有使用你的接口。您有 UsersDAO 和一个 UsersDAOImpl,但 Impl 与接口没有任何关系,因为您省略了“实现 UsersDAO”。不过,这不应该影响弹簧初始化。 (编辑 - 没关系,它在类之上,没有看到它 - 但是,你只是在创建一个 bean 并在 spring 中使用它 - 你并不需要这里的接口)。

    通常当我看到这个错误时,要么是因为我 a) 拼错了 bean 名称,所以没有这样的 bean(你还没有这样做)或者 b) 因为由于某种原因无法实例化 bean .您可以发布完整的堆栈跟踪吗?

    【讨论】:

    • 2009 年 7 月 10 日下午 3:39:54 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息:正在刷新 org.springframework.context.support.ClassPathXmlApplicationContext@133f1d7:显示名称 [org.springframework. context.support.ClassPathXmlApplicationContext@133f1d7];启动日期 [格林威治标准时间 2009 年 7 月 10 日星期五 15:39:53];上下文层次结构的根 2009 年 7 月 10 日下午 3:39:54 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO:从类路径资源加载 XML bean 定义 [Resources/contactmanagement.xml]
    • 2009 年 7 月 10 日下午 3:39:54 org.springframework.context.support.AbstractApplicationContext 获得FreshBeanFactory 信息:应用程序上下文的 Bean 工厂 [org.springframework.context.support.ClassPathXmlApplicationContext@133f1d7]:org .springframework.beans.factory.support.DefaultListableBeanFactory@11ddcde 2009 年 7 月 10 日下午 3:39:55 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 信息:在 org.springframework.beans.factory.support 中预实例化单例.DefaultListableBeanFactory@11ddcde:定义bean [];工厂层次结构的根
    • 线程“主”org.springframework.beans.factory.NoSuchBeanDefinitionException 中的异常:在 org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java 中未定义名为“usersdao”的 bean :391) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:233) 的 org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:999)
    • 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:170) 在 org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:883) 在 main .contactmanagement.main(contactmanagement.java:20) Java 结果:1
    • 您在下面提到了会话工厂异常,以及“找不到类”,这表明您在运行环境中缺少一个 jar。为了简化你的生活,我建议首先在没有休眠的情况下运行它,只需让 spring 加载类。然后至少你会验证你已经正确连接了那块。
    【解决方案5】:

    尝试使用

    context.getBeansOfType(UserDaoImpl.class);
    

    context.getBeansOfType(UserDao.class);
    

    确保没有错别字。

    【讨论】:

    • 感谢您的回复。我做了这个 UsersDAO usersdao = (UsersDAO) ctx.getBeansOfType(UsersDAO.class);我在线程“main”java.lang.ClassCastException 中得到了这个错误异常:java.util.LinkedHashMap 无法转换为 Dao.UsersDAO
    • 该方法返回一个 Map,而不是 bean 本身。只需执行类似 System.out.println(ctx.getBeansOfType(UserDao.class));
    【解决方案6】:

    在每次更改配置文件后清理和重建项目也是值得的,以确保它们真正移动到已编译的类并在您运行应用程序时使用。

    【讨论】:

    • 谢谢。错误信息已更改。我现在有这个:引起:java.lang.ClassNotFoundException:org.springframework.orm.hibernate3.annotation.SessionFactoryBean,我认为这与我关于sessionFactory和属性setSessionFactory的问题有关
    【解决方案7】:

    这是在黑暗中拍摄的,但请尝试在 Netbeans 上进行清理并构建。后台自动编译不会更新 .War 文件中的 XML。

    【讨论】:

      【解决方案8】:

      大家好,感谢您一直以来帮助我解决问题。实际上,我通过查看堆栈消息解决了问题,并更正了 hbm 文件中大部分时间的拼写错误和错误引用,并更正了区分大小写属性的 pojo。而且我不必在任何 daos 中创建 sessionFactory 属性。 现在我在第一个问题中所说的很好。虽然大多数 crud 函数都在工作,但我在返回用户对象而不是列表时仍然遇到问题。当然基于我使用的 id thgetHibernateTemplate.get(Users.class, id)

      但我想在实现从 arraylist 到 Users 类的简单转换后通过用户名返回用户对象是不可能的,这就是我所做的

      public Users GetUserByUsername(String username) {
        try
        {
            List userdetails = getHibernateTemplate().find("select u.user_id, u.username, u.password, u.city, u.country from Users u where u.username=?",username);
            Users u = new Users();
            u.setUser_id(Integer.parseInt(userdetails.get(0).toString()));
            u.setUsername(userdetails.get(1).toString());
            u.setPassword(userdetails.get(2).toString());
            u.setCity(userdetails.get(3).toString());
            u.setCountry(userdetails.get(4).toString());
           return u;
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            return new Users();
        }
      

      它不起作用。我猜它可能没有按顺序返回列,这就是为什么我将查询从“来自用户 u where u.username=?”更改为查询。到上面那个。

      1 如何从该查询返回用户对象? 2 返回用户列表对象呢?

      让我担心的另一件事是如何保存特定用户的联系人。您可以从我的映射文件中注意到,我的表联系人通过引用 user_id 来保持关系,这是用户表中的主键。在为contactdaoimpl 编写单元测试时,我遇到了几个问题。众所周知,联系人 pojo 中有一个用户类的属性。那么要保存 id 2 的联系人,例如我应该这样做吗?

      Users u = new Users();
      u.setUser_id(2); //supposing i have a way to get the id of the user
      Contacts c = new Contacts();
      c.setUser(u);
      c.setFirtname("young");// an so on for the rest of the properties
      contactdao.save(c);
      

      如果这是正确的,那么在测试类中我将不得不同时使用 userdao 和 contactdao。 3这样好吗? 我有一种感觉,测试不仅仅与用户联系,它与用户有依赖关系,但我仍然不知道如何将它们解耦,我什至不知道我应该这样做。 以便它。一旦消除了这三个担忧,那么我将成功完成一个基本但功能强大的应用程序与 spring hibernate。我想在那之后我会用它在某个地方发布一个教程。感谢阅读和帮助

      【讨论】:

        猜你喜欢
        • 2013-02-02
        • 2011-10-17
        • 2021-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-08
        • 2011-05-01
        • 2013-05-16
        相关资源
        最近更新 更多