zoukankan      html  css  js  c++  java
  • 笔记49 在Spittr应用中整合Hibernate

    在前边构建的Spittr应用中整合Hibernate

    由于最近所学的hibernate都是使用xml方式进行配置的,所以在与以Java方式配置的Spittr应用结合时就会出现一些小问题,在此进行总结。

    一、读取上下文

      因为原来的Spittr应用采用的是Java方式配置,没有用到xml。

      DispatcherServlet是Spring MVC的核心。按照传统的方式,像DispatcherServlet这样的Servlet会配置在 web.xml文件中。但是在Spittr应用中,使用Java将DispatcherServlet配置在Servlet容器中,而没有使用web.xml文件。代码如下所示:

    SpittrWebAppInitializer.java

     1 package myspittr.config;
     2 
     3 import javax.servlet.MultipartConfigElement;
     4 import javax.servlet.ServletRegistration.Dynamic;
     5 
     6 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
     7 
     8 public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
     9     @Override
    10     protected Class<?>[] getRootConfigClasses() {
    11         // TODO Auto-generated method stub
    12         return new Class<?>[] { RootConfig.class };
    13     }
    14 
    15     @Override
    16     protected Class<?>[] getServletConfigClasses() {
    17         // TODO Auto-generated method stub
    18         return new Class<?>[] { WebConfig.class };
    19     }
    20 
    21     @Override
    22     protected String[] getServletMappings() {
    23         // TODO Auto-generated method stub
    24         return new String[] { "/" };
    25     }
    26 
    27     @Override
    28     protected void customizeRegistration(Dynamic registration) {
    29         // TODO Auto-generated method stub
    30         registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads", 2097152, 4194304, 0));
    31     }
    32 
    33 }

    WebConfig.java

     1 package myspittr.config;
     2 
     3 import java.io.IOException;
     4 
     5 import org.springframework.context.MessageSource;
     6 import org.springframework.context.annotation.Bean;
     7 import org.springframework.context.annotation.ComponentScan;
     8 import org.springframework.context.annotation.Configuration;
     9 import org.springframework.context.support.ResourceBundleMessageSource;
    10 import org.springframework.web.multipart.MultipartResolver;
    11 import org.springframework.web.multipart.support.StandardServletMultipartResolver;
    12 import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    13 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    14 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    15 import org.springframework.web.servlet.view.InternalResourceViewResolver;
    16 
    17 @Configuration("WebConfig")
    18 @EnableWebMvc
    19 @ComponentScan({ "myspittr.web", "myspittr.data" })
    20 public class WebConfig extends WebMvcConfigurerAdapter {
    21     @Bean
    22     public InternalResourceViewResolver viewResolver() {
    23         InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    24         resolver.setPrefix("/WEB-INF/views/");
    25         resolver.setSuffix(".jsp");
    26         resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
    27         resolver.setExposeContextBeansAsAttributes(true);
    28         return resolver;
    29     }
    30 
    31     @Override
    32     public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    33         // TODO Auto-generated method stub
    34         configurer.enable();
    35     }
    36 
    37     @Bean
    38     public MessageSource messageSource() {
    39         ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    40         messageSource.setBasename("message");
    41         return messageSource;
    42     }
    43 
    44     @Bean
    45     public MultipartResolver multipartResolver() throws IOException {
    46         return new StandardServletMultipartResolver();
    47     }
    48 
    49     // @Bean
    50     // public MultipartResolver multipartResolver() throws IOException {
    51     // return new CommonsMultipartResolver();
    52     // }
    53 }

    RootConfig.java

     1 package myspittr.config;
     2 
     3 import org.springframework.context.annotation.ComponentScan;
     4 import org.springframework.context.annotation.ComponentScan.Filter;
     5 import org.springframework.context.annotation.Configuration;
     6 import org.springframework.context.annotation.FilterType;
     7 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
     8 
     9 @Configuration("RootConfig")
    10 @ComponentScan(basePackages = { "myspittr" }, excludeFilters = {
    11         @Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class) })
    12 public class RootConfig {
    13 
    14 }

      AbstractAnnotationConfigDispatcherServletInitializer的任意类都会自动地配置Dispatcher-Servlet和Spring应用上下文,Spring的应用上下文会位于应用程序的Servlet上下文之中。

    插入语:

      在Servlet 3.0环境 中,容器会在类路径中查找实现 javax.servlet.ServletContainerInitializer接口的类, 如果能发现的话,就会用它来配置Servlet容器。 Spring提供了这个接口的实现,名 为SpringServletContainerInitializer,这个类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给 它们来完成。Spring 3.2引入了一个便利的 WebApplicationInitializer基础实现,也就是AbstractAnnotationConfigDispatcherServletInitializer 因为我们的Spittr-WebAppInitializer扩展了 AbstractAnnotationConfig DispatcherServletInitializer(同时也就实现了 WebApplicationInitializer),因此当部署到Servlet 3.0容器中的时候,容器会自动发现它,并用它来配置Servlet上下文。
      尽管它的名字很长,但 是AbstractAnnotationConfigDispatcherServletInitializer使用起来很简便。在上述代码中,SpittrWebAppInitializer重写了三个方法。 第一个方法是getServletMappings(),它会将一个或多个路径映 射到DispatcherServlet上。在本例中,它映射的是“/”,这表示 它会是应用的默认Servlet。它会处理进入应用的所有请求。 为了理解其他的两个方法,我们首先要理解DispatcherServlet 和一个Servlet监听器(也就是ContextLoaderListener)的关系。

      两个应用(Spring和SpringMVC)上下文之间的关系:

      当DispatcherServlet启动的时候,它会创建Spring应用上下文,并加载配置文件或配置类中所声明的bean。在上述代码中的 getServletConfigClasses()方法中,我们要求DispatcherServlet加载应用上下文时,使用定义在WebConfig配置类(使用Java配置)中的bean。 但是在Spring Web应用中,通常还会有另外一个应用上下文。另外的这个应用上下文是由ContextLoaderListener创建的。 我们希望DispatcherServlet加载包含Web组件的bean,如控制器、视图解析器以及处理器映射,而ContextLoaderListener要加载应用中的其他bean。这些bean通常是驱动应用后端的中间层和数据层组件。

      实际上,AbstractAnnotationConfigDispatcherServletInitializer 会同时创建DispatcherServlet和 ContextLoaderListener。GetServlet-ConfigClasses() 方法返回的带有@Configuration注解的类将会用来定 义DispatcherServlet应用上下文中的 bean。getRootConfigClasses()方法返回的带 有@Configuration注解的类将会用来配 置ContextLoaderListener创建的应用上下文中的bean。 在本例中,根配置定义在RootConfig中,DispatcherServlet 的配置声明在WebConfig中。需要注意的是,通过 AbstractAnnotationConfigDispatcherServletInitializer来配置DispatcherServlet是传统web.xml方式的替代方案。如果你愿意的话,可以同时包含web.xml和 AbstractAnnotationConfigDispatcherServletInitializer,但这其实并没有必要。

      但是,问题是现在还不会使用Java方式对hibernate进行配置,所以没有办法只能采用xml方式配置。如果使用Java方式整合hibernate,那么将hibernate相关的bean放入WebConfig.java中即可。

      需要注意的是,以xml方式整合hibernate时,需要在web.xml中进行如下配置:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
     5 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" id="WebApp_1529217958650">
     6     <!-- 配置Spring IOC 容器 -->
     7     <context-param>
     8         <param-name>contextConfigLocation</param-name>
     9         <param-value>classpath:applicationContext.xml</param-value>
    10     </context-param>
    11     <listener>
    12         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    13     </listener>
    14 
    15     <!-- 配置Springmvc的核心控制器 -->
    16     <servlet>
    17         <servlet-name>dispatcherServlet</servlet-name>
    18         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    19         <init-param>
    20             <param-name>contextConfigLocation</param-name>
    21             <param-value>classpath:springmvc.xml</param-value>
    22         </init-param>
    23         <load-on-startup>1</load-on-startup>
    24     </servlet>
    25     <servlet-mapping>
    26         <servlet-name>dispatcherServlet</servlet-name>
    27         <url-pattern>/*</url-pattern>
    28     </servlet-mapping>
    29     <!-- 配置编码方式过滤器,且必须配置在所有的过滤器最前面 -->
    30     <filter>
    31         <filter-name>characterEncodingFilter</filter-name>
    32         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    33         <init-param>
    34             <param-name>encoding</param-name>
    35             <param-value>UTF-8</param-value>
    36         </init-param>
    37     </filter>
    38     <filter-mapping>
    39         <filter-name>characterEncodingFilter</filter-name>
    40         <url-pattern>/*</url-pattern>
    41     </filter-mapping>
    42     <!-- 为了使用SpringMVC框架实现REST,需配置HiddenHttpMethodFilter -->
    43     <filter>
    44         <filter-name>hiddenHttpMethodFilter</filter-name>
    45         <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    46     </filter>
    47     <filter-mapping>
    48         <filter-name>hiddenHttpMethodFilter</filter-name>
    49         <url-pattern>/*</url-pattern>
    50     </filter-mapping>
    51     
    52 </web-app>

      但是其中DispatcherServlet和 ContextLoaderListener已经在SpittrWebAppInitializer.java中配置过了,所以要去掉。那么如何加载hibernate相关的bean呢?新建applicationContext.xml文件,在这里面存放有关hibernate的配置,具体代码如下所示:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
     4     xsi:schemaLocation="http://www.springframework.org/schema/beans
     5             http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
     6             http://www.springframework.org/schema/context
     7             http://www.springframework.org/schema/context/spring-context-4.1.xsd">
     8 
     9     <!-- 配置数据源 -->
    10     <context:property-placeholder location="classpath:/config/db.properties" />
    11 
    12     <!-- 配置DataSource -->
    13     <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
    14         <property name="user" value="${jdbc.user}"></property>
    15         <property name="password" value="${jdbc.password}"></property>
    16         <property name="driverClass" value="${jdbc.driverClass}"></property>
    17         <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
    18     </bean>
    19 
    20     <!-- 配置SeeionFactory -->
    21     <bean class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"
    22         id="sessionFactory">
    23         <!-- 配置数据源 -->
    24         <property name="dataSource" ref="dataSource"></property>
    25         <!-- 配置实体包(pojo) -->
    26         <property name="PhysicalNamingStrategy">
    27             <bean
    28                 class="org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl"></bean>
    29         </property>
    30         <property name="packagesToScan" value="com.Spittr.entity"></property>
    31 
    32         <!-- 配置Hibernate的常用属性 -->
    33         <property name="hibernateProperties">
    34             <props>
    35                 <!-- 数据库的方言 -->
    36                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    37                 <prop key="hibernate.show_sql">true</prop>
    38                 <prop key="hibernate.format_sql">true</prop>
    39                 <prop key="hibernate.hbm2ddl.auto">update</prop>
    40             </props>
    41         </property>
    42     </bean>
    43 
    44     <!-- 配置hibernate的事务管理器 -->
    45     <bean class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    46         <property name="sessionFactory" ref="sessionFactory"></property>
    47     </bean>
    48 </beans>

    如何加载这里面的bean呢?使用ClassPathXmlApplicationContext获取配置文件,然后使用getBean方法获取相应bean,即SessionFactory。

    代码如下:

    1 ApplicationContext ctx= new ClassPathXmlApplicationContext("/config/applicationContext.xml");
    2 SessionFactory sessionFactory=ctx.getBean(SessionFactory.class);

      classpath请参考:笔记48

    二、Spittr应用中数据的处理

    1.应用中只涉及到两个实体类,一个是spiitle,另一个是spitter。它俩之间的关系是:一个spitter可以对应多个spittle,多个spittle对应一个spitter。

    所以在spittle中增加下面代码:

     1     private Spitters spitters;    
     2         @ManyToOne
     3     @JoinColumn(name = "author")
     4     public Spitters getSpitters() {
     5         return spitters;
     6     }
     7 
     8     public void setSpitters(Spitters spitters) {
     9         this.spitters = spitters;
    10     }    

    在spitter中增加下面代码:

     1     Set<Spittles> spittles;    
     2         @OneToMany(fetch = FetchType.EAGER)
     3     @JoinColumn(name = "author")
     4     public Set<Spittles> getSpittles() {
     5         return spittles;
     6     }
     7 
     8     public void setSpittles(Set<Spittles> spittles) {
     9         this.spittles = spittles;
    10     }    

    2.Spittr中注册界面和发布页面分别对应实体类spitter和spittle,但是如果这两个实体类直接使用hibernate映射为数据库中的表时,会出现一些问题,因为有一些字段是不用存储在数据库当中的,比如说确认密码。所以需要新建两个实体类,用作与数据库的交互,而原来的spitter和spittle用来与应用交互。下面给出两个新的实体类:

    Spitters.java

     1 package com.Spittr.entity;
     2 
     3 import java.io.Serializable;
     4 import java.util.Set;
     5 
     6 import javax.persistence.Entity;
     7 import javax.persistence.FetchType;
     8 import javax.persistence.GeneratedValue;
     9 import javax.persistence.GenerationType;
    10 import javax.persistence.Id;
    11 import javax.persistence.JoinColumn;
    12 import javax.persistence.OneToMany;
    13 import javax.persistence.Table;
    14 
    15 @Entity
    16 @Table(name = "spitters")
    17 public class Spitters implements Serializable {
    18     /**
    19      * 
    20      */
    21     private static final long serialVersionUID = 1L;
    22 
    23     int id;
    24     String username;
    25     String password;
    26     String email;
    27     Set<Spittles> spittles;
    28 
    29     public Spitters() {
    30         // TODO Auto-generated constructor stub
    31     }
    32 
    33     public Spitters(String username, String password, String email) {
    34         super();
    35         this.username = username;
    36         this.password = password;
    37         this.email = email;
    38     }
    39 
    40     @Id
    41     @GeneratedValue(strategy = GenerationType.IDENTITY)
    42     public int getId() {
    43         return id;
    44     }
    45 
    46     public void setId(int id) {
    47         this.id = id;
    48     }
    49 
    50     public String getUsername() {
    51         return username;
    52     }
    53 
    54     public void setUsername(String username) {
    55         this.username = username;
    56     }
    57 
    58     public String getPassword() {
    59         return password;
    60     }
    61 
    62     public void setPassword(String password) {
    63         this.password = password;
    64     }
    65 
    66     public String getEmail() {
    67         return email;
    68     }
    69 
    70     public void setEmail(String email) {
    71         this.email = email;
    72     }
    73 
    74     @OneToMany(fetch = FetchType.EAGER)
    75     @JoinColumn(name = "author")
    76     public Set<Spittles> getSpittles() {
    77         return spittles;
    78     }
    79 
    80     public void setSpittles(Set<Spittles> spittles) {
    81         this.spittles = spittles;
    82     }
    83 
    84 }

    Spittles.java

      1 package com.Spittr.entity;
      2 
      3 import java.io.Serializable;
      4 
      5 import javax.persistence.Entity;
      6 import javax.persistence.GeneratedValue;
      7 import javax.persistence.GenerationType;
      8 import javax.persistence.Id;
      9 import javax.persistence.JoinColumn;
     10 import javax.persistence.ManyToOne;
     11 import javax.persistence.Table;
     12 
     13 @Entity
     14 @Table(name = "spittles")
     15 public class Spittles implements Serializable {
     16     /**
     17      * 
     18      */
     19     private static final long serialVersionUID = 1L;
     20     private int id;
     21     private Long spittleId;
     22     private String message;
     23     private String title;
     24     private String time;
     25     private String username;
     26     private String spittlePicture;
     27 
     28     private Spitters spitters;
     29 
     30     public Spittles() {
     31         // TODO Auto-generated constructor stub
     32     }
     33 
     34     public Spittles(Long spittleId, String message, String title, String time, String username, String spittlePicture) {
     35         this.spittleId = spittleId;
     36         this.message = message;
     37         this.title = title;
     38         this.time = time;
     39         this.username = username;
     40         this.spittlePicture = spittlePicture;
     41     }
     42 
     43     @Id
     44     @GeneratedValue(strategy = GenerationType.IDENTITY)
     45     public int getId() {
     46         return id;
     47     }
     48 
     49     public void setId(int id) {
     50         this.id = id;
     51     }
     52 
     53     public Long getSpittleId() {
     54         return spittleId;
     55     }
     56 
     57     public void setSpittleId(Long spittleId) {
     58         this.spittleId = spittleId;
     59     }
     60 
     61     public String getMessage() {
     62         return message;
     63     }
     64 
     65     public void setMessage(String message) {
     66         this.message = message;
     67     }
     68 
     69     public String getTitle() {
     70         return title;
     71     }
     72 
     73     public void setTitle(String title) {
     74         this.title = title;
     75     }
     76 
     77     public String getTime() {
     78         return time;
     79     }
     80 
     81     public void setTime(String time) {
     82         this.time = time;
     83     }
     84 
     85     public String getUsername() {
     86         return username;
     87     }
     88 
     89     public void setUsername(String username) {
     90         this.username = username;
     91     }
     92 
     93     public String getSpittlePicture() {
     94         return spittlePicture;
     95     }
     96 
     97     public void setSpittlePicture(String spittlePicture) {
     98         this.spittlePicture = spittlePicture;
     99     }
    100 
    101     @ManyToOne
    102     @JoinColumn(name = "author")
    103     public Spitters getSpitters() {
    104         return spitters;
    105     }
    106 
    107     public void setSpitters(Spitters spitters) {
    108         this.spitters = spitters;
    109     }
    110 
    111 }

    三、总结

  • 相关阅读:
    POJ1700 Crossing River
    Glad to see you! CodeForces
    Summer sell-off CodeForces
    atcoderI
    Selling Souvenirs CodeForces
    Array Division CodeForces
    Tea Party CodeForces
    Atcoder F
    Atcoder E
    Average Sleep Time CodeForces
  • 原文地址:https://www.cnblogs.com/lyj-gyq/p/9196460.html
Copyright © 2011-2022 走看看