笔记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 }

三、总结

posted @ 2018-06-18 22:01  雨落忧伤-  阅读(160)  评论(0编辑  收藏  举报