java 视图、dao、服务和控制器的基本 hibernate 和 spring mvc 集成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17736568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 14:48:55  来源:igfitidea点击:

basic hibernate and spring mvc integration of view, dao, service and controller

javaspringhibernatejakarta-eespring-mvc

提问by Masood Ahmad

Status:Thankful to the answers but No one has answered the Important tag description in reflection to my simple code given. (20 Jul 13)

Status:感谢答案,但没有人回答反映了我给出的简单代码的重要标签描述。(13 年 7 月 20 日)

I have read many tutorials and yet every thing just mixes up or is only as a specific example that looks tiny or abstract.

我已经阅读了很多教程,但每件事都只是混淆了,或者只是一个看起来很小或抽象的特定示例。

I really cannot make something get logical in my mind. May be I learn with specific actual code.

我真的无法让某些事情在我的脑海中变得合乎逻辑。可能是我用具体的实际代码学习。

Question:Can anyone show how to make the following incomplete code work completelywith spring 3.x and hibernate 4.x.

问题:任何人都可以展示如何work completely使用spring 3.x 和 hibernate 4.x制作以下不完整的代码



Important:

重要的:

I would like, even in this simple example, make sessionfactoryand database quering by hibernate in the Serviceclass (making boundry there as in large applications Service classes use many DAOs and commit transactions in one go)

我想,即使在这个简单的例子中,在 Service类中通过休眠进行sessionfactory和数据库查询(在大型应用程序中建立边界,Service 类使用许多 DAO 并一次性提交事务)

I forget where i read it, perhaps in the spring documentation - but it clearly said, don't put @Transactional on your DAOs :P so generally, your service tier is where you define your transaction boundaries. a service method is typically a chunk of things that if all pass, commit otherwise fail and rollback That may not be a diehard rule of course, but its how we architected our enterprise resource planning web core. I forget where i read it, perhaps in the spring documentation - but it clearly said, don't put @Transactional on your DAOs

我忘了我在哪里读过它,也许在 spring 文档中 - 但它清楚地说,不要将 @Transactional 放在你的 DAO 上:P 所以一般来说,你的服务层是你定义事务边界的地方。一个服务方法通常是一大块东西,如果全部通过,提交否则失败和回滚这当然可能不是一个顽固的规则,但它是我们如何构建我们的企业资源规划 web 核心的。我忘了我在哪里读过它,也许在 spring 文档中 - 但它清楚地说,不要把 @Transactional 放在你的 DAO 上

e.g http://blog.patouchas.net/technology/hibernate-dao-java-tutorial/like without spring ?

例如 http://blog.patouchas.net/technology/hibernate-dao-java-tutorial/就像没有弹簧一样?



The annotationsare missing or incorrect. What should be the correct annotations.

注释丢失或不正确。正确的注解应该是什么。

Would there be any spring.xml (other than the usual) for these classes in specific? I would like to prefer only annotations if it works. correct annotations like @component , service, repository, resource, autowired

这些类是否有任何 spring.xml(除了通常的)?如果它有效,我想只喜欢注释。正确的注释,如 @component 、服务、存储库、资源、自动装配

This is how I get the transaction generally

这就是我通常获得交易的方式

   Configuration configuration = new Configuration();
   configuration.configure();

   ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                                        .applySettings(configuration.getProperties())
                                        .buildServiceRegistry();

   SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
   Session session = sessionFactory.openSession();
   session.beginTransaction();
   session.getTransaction().commit();
   session.close();

now spring and hibernate

现在春天和冬眠

@Controller
public class UserController {
    private IUserService userService;

    @RequestMapping("/users")
    public String creatUser(){
        Users user = new Users();
        user.setEmail("[email protected]");
        user.setName("myname");
        userService.creatUser(user);
        return "user-creation-result";      
    }
}

public class UserService implements IUserService{
    private IUserDAO userDAO;
    public void creatUser(Users user){
        //what to do here
        //how to call the sessionfactory
        //and call it in a way that each call
        // gives the same instance
         userDAO.creatUser(user);        
    }
}

public class UserDAO implements IUserDAO{
    public void creatUser(Users user){
        // what to do here?
    }
}

this wont be so important though.

不过这不会那么重要。

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">org.postgresql.Driver</property>
        <property name="connection.url">jdbc:postgresql://localhost:5432/postgres</property>
        <property name="connection.username">postgres</property>
        <property name="connection.password">abc</property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">create</property>

        <!-- Names the annotated entity class -->

        <mapping class="taskmanagsetup.Boards" />
        <mapping class="taskmanagsetup.BoardPrivileges" />
        <mapping class="taskmanagsetup.Boxes" />
        <mapping class="taskmanagsetup.BoxPrivileges" />
        <mapping class="taskmanagsetup.Groups" />
        <mapping class="taskmanagsetup.Tasks" />
        <mapping class="taskmanagsetup.TaskPrivileges" />
        <mapping class="taskmanagsetup.Users" />

    </session-factory>

</hibernate-configuration>



@Entity
public class Users {
    @Id
    @GeneratedValue
    private long id;
    @ManyToMany
    private Collection<Groups> groupList = new ArrayList<Groups>();
    private String type; // admin / teamlead / normal
    private String name;
    private String email;
    private String password;
    @Lob
    private String description;
    private boolean isEnabled;

    /**
     * @return the id
     */
    public long getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(long id) {
        this.id = id;
    }

    /**
     * @return the groupdId
     */


    /**
     * @param groupdId the groupdId to set
     */


    /**
     * @return the type
     */
    public String getType() {
        return type;
    }

    /**
     * @param type the type to set
     */
    public void setType(String type) {
        this.type = type;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the email
     */
    public String getEmail() {
        return email;
    }

    /**
     * @param email the email to set
     */
    public void setEmail(String email) {
        this.email = email;
    }

    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }

    /**
     * @param password the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @return the isEnabled
     */
    public boolean isIsEnabled() {
        return isEnabled;
    }

    /**
     * @param isEnabled the isEnabled to set
     */
    public void setIsEnabled(boolean isEnabled) {
        this.isEnabled = isEnabled;
    }

    /**
     * @return the groupList
     */
    public Collection<Groups> getGroupList() {
        return groupList;
    }

    /**
     * @param groupList the groupList to set
     */
    public void setGroupList(Collection<Groups> groupList) {
        this.groupList = groupList;
    }

    /**
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    /**
     * @param description the description to set
     */
    public void setDescription(String description) {
        this.description = description;
    }
}

回答by Paul Vargas

If you are using Spring 3.x and Hibernate 4.x, you can consider a three-tier application architecture:

如果你使用的是 Spring 3.x 和 Hibernate 4.x,你可以考虑三层应用架构

Data tier

数据层

You could have an abstract base class for common DAO methods.

你可以有一个通用 DAO 方法的抽象基类。

public abstract class AbstractDAO<E extends Serializable, 
                                 PK extends Serializable> {

    private final transient Class<E> entityClass;

    public AbstractDAO(final Class<E> entityClass) {
        this.entityClass = entityClass;
    }

    protected abstract EntityManager getEntityManager();

    public final E find(final PK id) {
        return getEntityManager().find(entityClass, id);
    }

    // Another common methods

}

In every DAO implementation, you can put particular methods for that DAO.

在每个 DAO 实现中,您可以为该 DAO 放置特定的方法。

@Repository
public final class UserDAO extends AbstractDAO<User, Long> {

    @Autowired
    private transient EntityManagerFactory emf;

    public UserDAO() {
        super(User.class);
    }

    @Override
    protected EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    // particular methods for this DAO

}

Application tier

应用层

What if the user does not exist? Put this logic in this tier.

如果用户不存在怎么办?将此逻辑放在此层中。

@Service
public final class UserService {

    private static final Logger LOG = LoggerFactory.getLogger(UserService.class);

    @Autowired
    private transient UserDAO userDAO;

    public User findUser(final Long id) {
        return userDAO.find(id);
    }

}

Presentation tier

展示层

@Controller
@RequestMapping("/user")
public final class UserController {

    private static final Logger LOG = LoggerFactory
                            .getLogger(UserController.class);

    @Autowired
    private transient UserService userService;

    @RequestMapping(value = "/find/{id}", method = RequestMethod.GET)
    public void downloadImage(
            @PathVariable("id") final Long id, 
            final HttpServletResponse response) throws IOException {
        // 
    }

}


The web.xml, this contains the Application config and the Dispatcher config:

web.xml这包含应用程序的配置和调度配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name>MyWebApp</display-name>

  <!-- log4j -->
  <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:log4j.xml</param-value>
  </context-param>
  <context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>MyWebApp.root</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
  </listener>

  <!-- Spring -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!-- Welcome -->
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

The dispatcher-servlet.xml:

dispatcher-servlet.xml

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

  <context:component-scan base-package="···.mywebapp" use-default-filters="false">
      <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
  </context:component-scan>

  <mvc:annotation-driven />

</beans>

And if you want to avoid the persistence.xmlfile, you can have it in your applicationContext.xml:

如果你想避免该persistence.xml文件,你可以在你的applicationContext.xml

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

    <bean id="dataSource" class="···">
        <property name="URL" value="···" />
        <property name="user" value="···" />
        <property name="password" value="···" />
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource" p:packagesToScan="···.model">

        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" p:showSql="false" p:databasePlatform="org.hibernate.dialect.SQLServerDialect" />
        </property>

        <property name="jpaProperties">
            <props>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>

    </bean>

    <context:component-scan base-package="···.mywebapp" use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Repository" type="annotation"/>
        <context:include-filter expression="org.springframework.stereotype.Service" type="annotation"/>
    </context:component-scan>

</beans>

I hope this can help you.

我希望这可以帮助你。

回答by Daniel Robertus

i dont know the best practice but this code worked for me :

我不知道最佳实践,但这段代码对我有用:

i write HibernateUtil to connect to DB :

我写 HibernateUtil 连接到数据库:

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory;
    static {
        try {
            sessionFactory = new AnnotationConfiguration().configure()
                    .buildSessionFactory();
            System.out.println("session Factory = "+sessionFactory.toString()+" current session="+sessionFactory.getCurrentSession()+
                    " collection="+sessionFactory.getAllCollectionMetadata()+" collection="+sessionFactory.getStatistics());
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

one of my model :

我的模型之一:

import javax.persistence.Column;
import javax.persistence.Entity;

import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Product {

    @ManyToOne
    @JoinColumn(name = "providerid")
    private Provider provider;
    @Id
    private String productCode;
    private int nominal;
    private double buyPrice;
    private double sellPrice;
    @ManyToOne
    @JoinColumn(name = "supplierid")
    private Supplier supplier;

    public Product(){
    }

    public Product(String id){
        setProductCode(id);

    }

    //setter and getter
}

DAO :

道:

import java.util.List;

public interface ProductDAO {

    public void save(Product product, int mode);

    public List<Product> list();

    public Product get(String id);

}

DAO Implementation :

DAO 实现:

import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.util.HibernateUtil;
import com.util.SessionHelper;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class ProductDAOImpl implements ProductDAO {

    private HibernateTemplate hibernateTemplate;
    private TableIDDAO tableIDDao;

    public void setTableIDDao(TableIDDAO tableIDDao) {
        this.tableIDDao = tableIDDao;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

    @Override
    public void save(Product product, int mode) {
        SessionFactory sf = HibernateUtil.getSessionFactory();
        Session session = sf.getCurrentSession();
        Transaction tr = session.beginTransaction();
        session.saveOrUpdate(product);      
        tr.commit();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Product> list() {
        return hibernateTemplate.find(" from Product ");
    }

    @Override
    public Product get(String id) {
        List<Product> list = hibernateTemplate.find(" from Product where productCode='" + id + "'");
        Product c = null;
        if (!list.isEmpty()) {
            c = list.get(0);
        }
        return c;
    }
}

Controller (from controller we call dao - i write this long time ago so still use modelandview, its better if you use annotation cause modelandview is obsolete) :

控制器(从控制器我们称之为 dao - 我很久以前写过这个,所以仍然使用 modelandview,如果你使用注释会更好,因为 modelandview 已经过时了):

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.ui.ModelMap;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import com.util.SessionHelper;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

public class ProductController extends MultiActionController {

    private ProductDAO productDAO;

    public void setProductDAO(ProductDAO productDAO) {
        this.productDAO = productDAO;
    }

    public ProductController() {
        System.out.println("Masuk ke Contrutctor Product Controller");
    }

    public ModelAndView add(HttpServletRequest request,
            HttpServletResponse response, Product product) throws Exception {
        productDAO.save(product,mode);
        return new ModelAndView("redirect:list.htm");
    }

    public ModelAndView list(HttpServletRequest request,
            HttpServletResponse response,Page p) throws Exception {
        ModelMap modelMap = new ModelMap();
        modelMap.addAttribute("productList", page.paging(productDAO.list()));
        modelMap.addAttribute("product", new Product());
        return new ModelAndView("product", modelMap);
    }
}

My JSP :

我的 JSP :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
         pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>

<html>
    <body>
        <div class="content"> 
            <c:if test="${fn:length(productList) > 0}">
                <table cellpadding="5">
                    <tr class="even">
                        <th>Product Code</th>
                        <th>nominal</th>
                        <th>buy price</th>
                        <th>Sell Price</th>
                        <th>Provider</th>
                        <th>Supplier</th>
                    </tr>
                    <c:forEach items="${productList}" var="product" varStatus="status">
                            <td>${product.productCode}</td>
                            <td>${product.nominal}</td>
                            <td>${product.buyPrice}</td>
                            <td>${product.sellPrice}</td>
                            <td>${product.provider.namaProvider}</td>
                            <td>${product.supplier.name}</td>
                        </tr>
                    </c:forEach>
                </table>
            </c:if>
                    <p>Data Form</p>
            <form:form action="add.htm" commandName="product">
                <table>
                    <tr>
                        <td>Product Code :</td>
                        <td><form:input path="productCode" /></td>
                    </tr>
                    <tr>
                        <td>Nominal :</td>
                        <td><form:input path="nominal" /></td>
                    </tr>
                    <tr>
                        <td>Buy Price :</td>
                        <td><form:input path="buyPrice" /></td>
                    </tr>
                    <tr>
                        <td>Sell Price :</td>
                        <td><form:input path="sellPrice" /></td>
                    </tr>
                    <tr>
                        <td>Provider :</td>
                        <td><form:select path="provider.providerID"  modelAttribute="contact" >
                                <form:options items="${providerList}" itemValue="providerID" itemLabel="namaProvider" />
                            </form:select>
                        </td>
                    </tr>
                    <tr>
                        <td>Provider :</td>
                        <td><form:select path="supplier.supplierID"   >
                                <form:options items="${supplierList}" itemValue="supplierID" itemLabel="name" />
                            </form:select>
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2"><input type="submit" value="Register"></td>
                    </tr>
                </table>
            </form:form>
        </div>
    </body>
</html>

and you also need to configure your spring configuration and include it in your web.xml all jsp i put in /WEB-INF/pages/... its up to you if you want put it somewhere else

并且您还需要配置您的 spring 配置并将其包含在您的 web.xml 中所有我放在 /WEB-INF/pages/...

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

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/pages/" p:suffix=".jsp" />

    <bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
        <property name="driverClassName" value="org.springframework.jdbc.datasource.DriverManagerDataSource"/>
        <property name="url" value="jdbc:mysql://localhost:3306/yourdatabase"/>
        <property name="username" value="root"/>
        <property name="password" value="yourmysqlpassword"/>
    </bean>

    <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" />
        <property name="annotatedClasses">
            <list>
                <value>com.bean.Product</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
            </props>
        </property>
    </bean>

    <bean id="myProductDAO" class="com.dao.ProductDAOImpl">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

    <bean name="/product/*.htm" class="com.controller.ProductController" >
        <property name="productDAO" ref="myProductDAO" />
    </bean>

</beans>

also you need create hibernate.cf.xml in your root of your code :

您还需要在代码的根目录中创建 hibernate.cf.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/yourdatabase</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">yourmysqlpassword</property>
    <property name="hibernate.connection.driver_class"> org.hsqldb.jdbcDriver</property>
    <property name="current_session_context_class">thread</property>
    <property name="connection.pool_size">3</property>
    <property name="show_sql">true</property>
    <mapping class="com.bean.Product" />    
  </session-factory>
</hibernate-configuration>

i dont give you exactly the same to my real code, but i think its enough to give you an inspiration.

我不会给你和我的真实代码完全一样的,但我认为它足以给你一个灵感。