Copy this link when reproducing:
http://www.casperlee.com/en/y/blog/180
I've learned several techniques that I need to know to create this application, and I also have added the "Birthday of celebrities" information to my "Today in History" application. Now it is time to finish the main part of this application: displaying all kinds of information of today in history.






1. Run the following command to create extra tables (dayDeath, dayEvent, dayFestival), and add columns to the table "day":
mysql> alter table day
-> add column dayCeleb varchar(60) null;
mysql> alter table day
-> add column dayCelebImage varchar(100) null;
mysql> alter table day
-> add column dayCelebDesc varchar(2000) null;
mysql> create table dayDeath (
-> dayDeathId int(4) primary key not null auto_increment,
-> dayDeathDayId int(4) not null,
-> dayDeathCelebName varchar(100) not null,
-> dayDeathCelebTitle varchar(500) null,
-> dayDeathYear char(4) not null,
-> dayDeathCelebAchievement varchar(500) null,
-> dayDeathCelebImage varchar(60) null
-> );
mysql> alter table dayDeath
-> add constraint fk_dayDeathDayId foreign key (dayDeathDayId) references day(dayId);
mysql> create table dayEvent (
-> dayEventId int(4) primary key not null auto_increment,
-> dayEventDayId int(4) not null,
-> dayEventYear char(4) not null,
-> dayEventDesc varchar(2000) not null,
-> dayEventImage varchar(100) null,
-> dayEventImageDesc varchar(60) null
-> );
mysql> alter table dayEvent
-> add constraint fk_dayEventDayId foreign key (dayEventDayId) references day(dayId);
mysql> create table dayFestival (
-> dayFestivalId int(4) primary key not null auto_increment,
-> dayFestivalDayId int(4) not null,
-> dayFestivalName varchar(60) not null,
-> dayFestivalDesc varchar(2000) not null,
-> dayFestivalDescShort varchar(200) null,
-> dayFestivalSortKey char(4) null default '0000'
-> );
mysql> alter table dayFestival
-> add constraint fk_dayFestivalDayId foreign key (dayFestivalDayId) references day(dayId);
FYI: Check the link http://www.casperlee.com/en/l/blog/90 for more information about dealing with MySQL database.
2. To support Chinese, run the following command to change the character set configuration of the tables:
mysql> alter table day convert to character set utf8;
mysql> alter table dayBirth convert to character set utf8;
mysql> alter table dayDeath convert to character set utf8;
mysql> alter table dayEvent convert to character set utf8;
mysql> alter table dayFestival convert to character set utf8;
3. Create a class named "DayEvent" in the package "com.casperlee.today.domain":
package com.casperlee.today.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="dayEvent")
public class DayEvent {
@Id
@Column(name="dayEventId")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="dayEventYear")
private String year;
@Column(name="dayEventDesc")
private String eventDescription;
@Column(name="dayEventImage")
private String eventImage;
@Column(name="dayEventImageDesc")
private String eventImageDescription;
@ManyToOne(targetEntity=Day.class, fetch = FetchType.LAZY)
@JoinColumn(name="dayEventDayId", nullable = false, updatable = false)
private Day day;
public DayEvent() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getEventDescription() {
return eventDescription;
}
public void setEventDescription(String eventDescription) {
this.eventDescription = eventDescription;
}
public String getEventImage() {
return eventImage;
}
public void setEventImage(String eventImage) {
this.eventImage = eventImage;
}
public String getEventImageDescription() {
return eventImageDescription;
}
public void setEventImageDescription(String eventImageDescription) {
this.eventImageDescription = eventImageDescription;
}
public Day getDay() {
return day;
}
public void setDay(Day day) {
this.day = day;
}
@Override
public String toString() {
return this.eventDescription;
}
}
4. Create a class named "DayDeath" in the package "com.casperlee.today.domain":
package com.casperlee.today.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="dayDeath")
public class DayDeath {
@Id
@Column(name="dayDeathId")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="dayDeathCelebName")
private String celebrityName;
@Column(name="dayDeathCelebTitle")
private String celebrityTitle;
@Column(name="dayDeathYear")
private String year;
@Column(name="dayDeathCelebAchievement")
private String celebrityAchievement;
@Column(name="dayDeathCelebImage")
private String celebrityImage;
@ManyToOne(targetEntity=Day.class, fetch = FetchType.LAZY)
@JoinColumn(name="dayDeathDayId", nullable = false, updatable = false)
private Day day;
public DayDeath() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCelebrityName() {
return celebrityName;
}
public void setCelebrityName(String celebrityName) {
this.celebrityName = celebrityName;
}
public String getCelebrityTitle() {
return celebrityTitle;
}
public void setCelebrityTitle(String celebrityTitle) {
this.celebrityTitle = celebrityTitle;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getCelebrityAchievement() {
return celebrityAchievement;
}
public void setCelebrityAchievement(String celebrityAchievement) {
this.celebrityAchievement = celebrityAchievement;
}
public String getCelebrityImage() {
return celebrityImage;
}
public void setCelebrityImage(String celebrityImage) {
this.celebrityImage = celebrityImage;
}
public Day getDay() {
return day;
}
public void setDay(Day day) {
this.day = day;
}
@Override
public String toString() {
return this.celebrityName;
}
}
5. Create a class named "DayFestival" in the package "com.casperlee.today.domain":
package com.casperlee.today.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="dayFestival")
public class DayFestival {
@Id
@Column(name="dayFestivalId")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="dayFestivalName")
private String festivalName;
@Column(name="dayFestivalDesc")
private String festivalDescription;
@Column(name="dayFestivalDescShort")
private String festivalDescriptionShort;
@Column(name="dayFestivalSortKey")
private String sortKey;
@ManyToOne(targetEntity=Day.class, fetch = FetchType.LAZY)
@JoinColumn(name="dayFestivalDayId", nullable = false, updatable = false)
private Day day;
public DayFestival() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFestivalName() {
return festivalName;
}
public void setFestivalName(String festivalName) {
this.festivalName = festivalName;
}
public String getFestivalDescription() {
return festivalDescription;
}
public void setFestivalDescription(String festivalDescription) {
this.festivalDescription = festivalDescription;
}
public String getFestivalDescriptionShort() {
return festivalDescriptionShort;
}
public void setFestivalDescriptionShort(String festivalDescriptionShort) {
this.festivalDescriptionShort = festivalDescriptionShort;
}
public String getSortKey() {
return sortKey;
}
public void setSortKey(String sortKey) {
this.sortKey = sortKey;
}
public Day getDay() {
return day;
}
public void setDay(Day day) {
this.day = day;
}
@Override
public String toString() {
return this.festivalName;
}
}
6. Modify the configuration file "WebContent\WEB-INF\config\springmvc-config.xml" to include the classes that have been just created:
<bean id="hibernateAnnotatedSessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
...
<property name="annotatedClasses">
<list>
...
<value>com.casperlee.today.domain.DayEvent</value>
<value>com.casperlee.today.domain.DayDeath</value>
<value>com.casperlee.today.domain.DayFestival</value>
...
</list>
</property>
...
</bean>
7. Modify the class "com.casperlee.today.domain.Day" to include the columns and sub-level tables that have been just added:
package com.casperlee.today.domain;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
@Entity
@Table(name="day")
public class Day {
@Id
@Column(name="dayId")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="dayKey")
private String key;
@Column(name="dayName")
private String name;
@Column(name="dayDescription")
private String description;
@Column(name="dayCeleb")
private String celebrityOfToday;
@Column(name="dayCelebImage")
private String celebrityImagePath;
@Column(name="dayCelebDesc")
private String celebrityDescription;
@OneToMany(targetEntity=DayEvent.class, cascade = CascadeType.ALL,
mappedBy = "day", fetch = FetchType.LAZY)
@OrderBy("year ASC")
private List<DayEvent> historicalEvents;
@OneToMany(targetEntity=DayBirth.class, cascade = CascadeType.ALL,
mappedBy = "day", fetch = FetchType.LAZY)
@OrderBy("year ASC")
private List<DayBirth> celebrityBirthdays;
@OneToMany(targetEntity=DayDeath.class, cascade = CascadeType.ALL,
mappedBy = "day", fetch = FetchType.LAZY)
@OrderBy("year ASC")
private List<DayDeath> celebrityDeaths;
@OneToMany(targetEntity=DayFestival.class, cascade = CascadeType.ALL,
mappedBy = "day", fetch = FetchType.LAZY)
@OrderBy("sortKey ASC")
private List<DayFestival> festivals;
public Day() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCelebrityOfToday() {
return celebrityOfToday;
}
public void setCelebrityOfToday(String celebrityOfToday) {
this.celebrityOfToday = celebrityOfToday;
}
public String getCelebrityImagePath() {
return celebrityImagePath;
}
public void setCelebrityImagePath(String celebrityImagePath) {
this.celebrityImagePath = celebrityImagePath;
}
public String getCelebrityDescription() {
return celebrityDescription;
}
public void setCelebrityDescription(String celebrityDescription) {
this.celebrityDescription = celebrityDescription;
}
public List<DayEvent> getHistoricalEvents() {
return historicalEvents;
}
public void setHistoricalEvents(List<DayEvent> historicalEvents) {
this.historicalEvents = historicalEvents;
}
public List<DayBirth> getCelebrityBirthdays() {
return celebrityBirthdays;
}
public void setCelebrityBirthdays(List<DayBirth> celebrityBirthdays) {
this.celebrityBirthdays = celebrityBirthdays;
}
public List<DayDeath> getCelebrityDeaths() {
return celebrityDeaths;
}
public void setCelebrityDeaths(List<DayDeath> celebrityDeaths) {
this.celebrityDeaths = celebrityDeaths;
}
public List<DayFestival> getFestivals() {
return festivals;
}
public void setFestivals(List<DayFestival> festivals) {
this.festivals = festivals;
}
@Override
public String toString () {
return this.name;
}
}
8. Create a folder named "Images" in the "WebContent" directory, so that we can store images here and refer to them in the application.
Note: we need to add the following text into configuration file "WebContent\WEB-INF\config\springmvc-config.xml" to indicate the "Images" folder contains static resources:
<mvc:resources mapping="/Images/**" location="/Images/"/>
9. Create a folder named "css" in the "WebContent" directory, and create a file named "main.css" in the "css" folder. Here is the content of the file "main.css":
#divCatalog {
text-align: left;
margin: 48px auto 0px 48px;
}
#divCelebOfToday {
text-align: left;
margin: 48px auto;
}
#divEvents {
text-align: left;
margin: 48px auto;
}
#divCelebBorn {
text-align: left;
margin: 48px auto;
}
#divCelebPassed {
text-align: left;
margin: 48px auto;
}
#divFestivals {
text-align: left;
margin: 48px auto;
}
10. Modify the .jsp file "WebContent\WEB-INF\jsp\DayForm.jsp" to display more information:
<%@ page contentType="text/html; charset=gb2312"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML>
<html>
<head>
<title>历史上的今天</title>
<style type="text/css">@import url("<c:url value="/css/main.css"/>");</style>
</head>
<body>
<div>
<h1>${day.name}</h1>
</div>
<div>
<p>
${day.description}
</p>
</div>
<div id="divCatalog">
<h3>目录</h3>
<c:if test="${day.celebrityOfToday != null && day.celebrityOfToday != ''}">
<a href="#divCelebOfToday">今日人物</a><br />
</c:if>
<a href="#divEvents">重大事件</a><br />
<a href="#divCelebBorn">出生名人</a><br />
<a href="#divCelebPassed">逝世名人</a><br />
<a href="#divFestivals">节日风俗</a>
</div>
<c:if test="${day.celebrityOfToday != null && day.celebrityOfToday != ''}">
<div id="divCelebOfToday">
<div>
<h2>今日人物</h2>
</div>
<div>
<img alt="${day.celebrityOfToday}" src="${day.celebrityImagePath}" width="600px" height="100%">
</div>
<div>
<p>
${day.celebrityDescription}
</p>
</div>
</div>
</c:if>
<div id="divEvents">
<h2>重大事件</h2>
<p>
<c:forEach items="${day.historicalEvents}" var="dayEvent">
<div>
${dayEvent.year}, ${dayEvent.eventDescription}
</div>
</c:forEach>
</p>
</div>
<div id="divCelebBorn">
<h2>出生名人</h2>
<p>
<c:forEach items="${day.celebrityBirthdays}" var="dayBirth">
<div>
${dayBirth.year}, ${dayBirth.celebrityName}, ${dayBirth.celebrityTitle}
<c:if test="${dayBirth.celebrityAchievement != null && dayBirth.celebrityAchievement != ''}">
(主要成就:${dayBirth.celebrityAchievement})
</c:if>
</div>
</c:forEach>
</p>
</div>
<div id="divCelebPassed">
<h2>逝世名人</h2>
<p>
<c:forEach items="${day.celebrityDeaths}" var="dayDeath">
<div>
${dayDeath.year}, ${dayDeath.celebrityName}, ${dayDeath.celebrityTitle}
<c:if test="${dayDeath.celebrityAchievement != null && dayDeath.celebrityAchievement != ''}">
(主要成就:${dayDeath.celebrityAchievement})
</c:if>
</div>
</c:forEach>
</p>
</div>
<div id="divFestivals">
<h2>节日风俗</h2>
<p>
<c:forEach items="${day.festivals}" var="dayFestival">
<div>
<h3>${dayFestival.festivalName}</h3>
</div>
<div>
<p>
${dayFestival.festivalDescriptionShort}
</p>
</div>
<div>
<p>
${dayFestival.festivalDescription}
</p>
</div>
</c:forEach>
</p>
</div>
</body>
</html>
11. Here is the complete structure of the application:

12. Right click on the "today" project, select "Run As -> Run on Server" on the popped menu to test if it works now.




13. Yeah! Finished!
If you are interested, welcome to download the source code for your own purpose: