Spring的核心思想是解藕,对象的初始化在xml中描述出来了,应用程序不再需要new出一个对象并对其进行各种初始化,而是从Spring容器中取出这些初始化好的对象。下面来配置Spring,使用myeclipse添加spring特性后会得到一个applicationContext.xml,Spring会读取这个配置文件初始化一些bean以供我们注入。我先贴出我修改过的applicationContext.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" xmlns:p="http://www.springframework.org/schema/p" xmlns:content="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- 注解扫描包 --> <content:annotation-config/> <content:component-scan base-package="com.flyding.jpress"/> <!-- 使用占位符读取配置信息 --> <bean id="placeHolder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath:config.properties</value> </property> </bean> <!-- 数据源 使用hibernate所建议的c3p0数据源--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.psw}" /> <property name="initialPoolSize"><value>${hibernate.c3p0.initialPoolSize}</value></property> <property name="minPoolSize"><value>${hibernate.c3p0.minPoolSize}</value></property> <property name="maxPoolSize"><value>${hibernate.c3p0.maxPoolSize}</value></property> <property name="maxIdleTime"><value>${hibernate.c3p0.timeout}</value></property> <property name="maxStatements"><value>${hibernate.c3p0.max_statement}</value></property> <property name="acquireIncrement"><value>${hibernate.c3p0.acquireIncrement}</value></property> </bean> <!-- hibernate4中的LocalSessionFactoryBean直接提供了annotation支持,这一点跟hibernate3有所不同 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="javax.persistence.validation.mode">none</prop> </props> </property> <property name="packagesToScan"> <value>com.flyding.jpress.model</value> </property> </bean> <!-- 事务管理 --> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 植入点 --> <aop:config> <!-- 定义一个植入点 --> <aop:pointcut id="daoTransactionPt" expression="execution(public * com.flyding.jpress.dao.impl.*.*(..))"/> <!-- 配置这个植入点将参考怎样的智者 --> <aop:advisor pointcut-ref="daoTransactionPt" advice-ref="daoTransactionAdvice"/> </aop:config> <!-- 配置事务智者 --> <tx:advice id="daoTransactionAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 用于注解方式配置事务 --> <tx:annotation-driven transaction-manager="txManager"/> </beans>这份配置文件是我从上一个项目中copy过来的,复用率非常高,稍作修改就能在新的项目中使用。基于SSH的开发流程非常清晰,不会让人无从下手,从Spring的配置文件开始,我们就已经看到是Spring在集成Hibernate了。将经常需要修改的数据源信息分离在独立的config.properties文件中,使用placeHolder占位符读取配置信息并将其填入。下面是一份config.properties文件:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/jpress jdbc.username=root jdbc.psw=******** hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true; hibernate.c3p0.initialPoolSize=10 hibernate.c3p0.minPoolSize=10 hibernate.c3p0.maxPoolSize=50 hibernate.c3p0.timeout=300 hibernate.c3p0.max_statement=50 hibernate.c3p0.acquireIncrement=5接下来需要着手编写Hibernate的model了,我习惯于使用annotation配置ORM映射关系,数据库中一共有10张表,其中有两个表是多对多的中间表,这两表是不产生模型的。所以我们一共需要生成8个java文件,并在文件中使用注解的方式描述类与数据库表的关系,myeclipse为我们提供了直接生成的工具,下面是一份由myeclipse生成的model:
package com.flyding.jpress.model;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* User entity. @author flyding.com
*/
@Entity
@Table(name = "jp_user", catalog = "jpress")
public class User implements java.io.Serializable {
private static final long serialVersionUID = 9010981240846378504L;
// Fields
private Long id;
private String username;
private String nickname;
private String password;
private String email;
private Timestamp registerDt;
private String userUrl;
private Integer userLevel;
private Set<Entry> entries = new HashSet<Entry>(0);
private Set<UserMeta> userMetas = new HashSet<UserMeta>(0);
// Constructors
/** default constructor */
public User() {
}
/** minimal constructor */
public User(String username, String password, String email,
Timestamp registerDt, Integer userLevel) {
this.username = username;
this.password = password;
this.email = email;
this.registerDt = registerDt;
this.userLevel = userLevel;
}
/** full constructor */
public User(String username, String nickname, String password,
String email, Timestamp registerDt, String userUrl,
Integer userLevel, Set<Entry> entries, Set<UserMeta> userMetas) {
this.username = username;
this.nickname = nickname;
this.password = password;
this.email = email;
this.registerDt = registerDt;
this.userUrl = userUrl;
this.userLevel = userLevel;
this.entries = entries;
this.userMetas = userMetas;
}
// Property accessors
@Id
@GeneratedValue
@Column(name = "id", unique = true, nullable = false)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "username", nullable = false, length = 50)
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(name = "nickname", length = 50)
public String getNickname() {
return this.nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
@Column(name = "password", nullable = false, length = 50)
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
@Column(name = "email", nullable = false, length = 50)
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
@Column(name = "register_dt", nullable = false, length = 19)
public Timestamp getRegisterDt() {
return this.registerDt;
}
public void setRegisterDt(Timestamp registerDt) {
this.registerDt = registerDt;
}
@Column(name = "user_url", length = 50)
public String getUserUrl() {
return this.userUrl;
}
public void setUserUrl(String userUrl) {
this.userUrl = userUrl;
}
@Column(name = "user_level", nullable = false)
public Integer getUserLevel() {
return this.userLevel;
}
public void setUserLevel(Integer userLevel) {
this.userLevel = userLevel;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
public Set<Entry> getEntries() {
return this.entries;
}
public void setEntries(Set<Entry> entries) {
this.entries = entries;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
public Set<UserMeta> getUserMetas() {
return this.userMetas;
}
public void setUserMetas(Set<UserMeta> userMetas) {
this.userMetas = userMetas;
}
}
生成8个类似的数据层model后,我们的项目工程如图所示:
今天先写到这里,下一章我们将来设计数据库接口,原则上的构架是:一个数据库model会对应一个DAO,并有一个Impl类来实现这个接口,将这个Impl使用Spring的annotation注解为componet供将来的业务层注入使用。实际操作过程中,我们会首先设计一个通用接口BaseDao,在通用接口中使用JAVA泛型定义一组重用率非常高的增删改查操作,我们会有一个通用接口的通用抽象实现BaseDaoImpl,各个DAO接口继承自这个通用数据接口BaseDao,各个DAO的Impl继承自BaseDaoImpl并实现各自的接口,这样说上去比较绕,下一章实际操作起来其实层次感非常清晰。