本文提供Struts2整合Spring Hibernate的CRUD的实例的源代码
1. 数据库脚本,数据库采用MySQL 5.0
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(32) NOT NULL,
`password` varchar(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2. 几个重要的文件
web.xml
<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app version=”2.5″ xmlns=”[url=http://java.sun.com/xml/ns/javaee]http://java.sun.com/xml/ns/javaee[/url]”
xmlns:xsi=”[url=http://www.w3.org/2001/XMLSchema-instance]http://www.w3.org/2001/XMLSchema-instance[/url]”
xsi:schemaLocation=”[url=http://java.sun.com/xml/ns/javaee]http://java.sun.com/xml/ns/javaee[/url]
[url=http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd]http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd[/url]“>
<!– spring的应用上下文 –>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<!– struts2 过滤器 –>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!– spring的监听器,以便在启动时就自动加载spring的配置 –>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!– OpenSessionInViewFilter过滤器 –>
<filter>
<filter-name>lazyLoadingFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>lazyLoadingFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>/user/userAdd.jsp</welcome-file>
</welcome-file-list>
</web-app>
applicationContext.xml
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”[url=http://www.springframework.org/schema/beans]http://www.springframework.org/schema/beans[/url]”
xmlns:xsi=”[url=http://www.w3.org/2001/XMLSchema-instance]http://www.w3.org/2001/XMLSchema-instance[/url]”
xsi:schemaLocation=”[url=http://www.springframework.org/schema/beans]http://www.springframework.org/schema/beans[/url] [url=http://www.springframework.org/schema/beans/spring-beans-2.0.xsd]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]“>
<bean id=”dataSource”
class=”org.apache.commons.dbcp.BasicDataSource”>
<property name=”driverClassName”
value=”com.mysql.jdbc.Driver”>
</property>
<property name=”url”
value=”jdbc:mysql://localhost:3306/catalog”>
</property>
<property name=”username” value=”root”></property>
<property name=”password” value=”ethip”></property>
</bean>
<bean id=”sessionFactory”
class=”org.springframework.orm.hibernate3.LocalSessionFactoryBean”>
<property name=”dataSource”>
<ref bean=”dataSource” />
</property>
<property name=”hibernateProperties”>
<props>
<prop key=”hibernate.dialect”>
org.hibernate.dialect.MySQLDialect
</prop>
</props>
</property>
<property name=”mappingResources”>
<list>
<value>org/ethip/catalog/model/User.hbm.xml</value>
</list>
</property>
</bean>
<bean id=”UserDAO”>
<property name=”sessionFactory”>
<ref [...]
Hibernate入门篇三:建立hibernate应用程序的步骤
(我的IDE: MyEclipse_6.0.1GA_E3.3.1_FullStackInstaller)
1.建立一个Java Project(或者Web Project)
(Hibernate主要是与数据库交互,初学时就新建一个Java Project吧)
2.在数据库中创建数据库和表
e.g. datebase name = test,
test.table name =login
表login的字段可参照 UserInfo.hbm.xml或者POJO类的属性
3.创建持久化类
4.导入hibernate的jar
利用myeclipse自动完成。其间会生成配置文件hibernate.cfg.xml。
5.创建数据库关系映射文件
e.g.UserInfo.hbm.cml
6.建立测试类
一、run()和start()
这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由Java的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void.
二、关键字Synchronized
这个关键字用于保护共享数据,当然前提是要分清哪些数据是共享数据。每个对象都有一个锁标志,当一个线程访问该对象时,被Synchronized修饰的数据将被“上锁”,阻止其他线程访问。当前线程访问完这部分数据后释放锁标志,其他线程就可以访问了。
以下是引用片段:
public ThreadTest implements Runnable
{
public synchronized void run(){
for(int i=0;i<10;i++)
{
System.out.println(“ ” + i);
}
}
public static void main(String[] args)
{
Runnable r1 = new ThreadTest();
Runnable r2 = new ThreadTest();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
以上这段程序中的 i 变量并不是共享数据,也就是这里的Synchronized关键字并未起作用。因为t1,t2两个线程是两个对象(r1,r2)的线程。不同的对象其数据是不同的,所以r1和r2两个对象的i变量是并不是共享数据。
当把代码改成如下:Synchronized关键字才会起作用
以下是引用片段:
Runnable r = new ThreadTest();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
三、sleep()
使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是如果有Synchronized同步块,其他线程仍然不同访问共享数据。注意该方法要捕获异常
比如有两个线程同时执行(没有Synchronized),一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完成后,低优先级的线程才能执行;但当高优先级的线程sleep(5000)后,低优先级就有机会执行了。
总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。
四、join()
join()方法使调用该方法的线程在此之前执行完毕,也就是等待调用该方法的线程执行完毕后再往下继续执行。注意该方法也要捕获异常。
五、yield()
它与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
六、wait()和notify()、notifyAll()
这三个方法用于协调多个线程对共享数据的存取,所以必须在Synchronized语句块内使用这三个方法。前面说过Synchronized 这个关键字用于保护共享数据,阻止其他线程对共享数据的存取。但是这样程序的流程就很不灵活了,如何才能在当前线程还没退出Synchronized数据块时让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。
wait()方法使当前线程暂停执行并释放对象锁标志,让其他线程可以进入Synchronized数据块,当前线程被放入对象等待池中。当调用 notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有
锁标志等待池中的线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。
notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。
Map是一个保存键值对的对象,根据键值可以找到它对应的值。键必须是唯一的,但是值可以重复。HashMap类提供了map接口的主要实现,它使用hash table来实现map接口。这就使得一些常见的操作如get()和put()所用的时间基本不变。
如下代码是一个使用hashmap的实例,它提供了account信息和account balance的对应:
import java.util.*;
public class HashMapDemo {
public static void main( String[] args) {
HashMap hm = new HashMap();
hm.put(“Rohit”, new Double(3434.34));
hm.put(“Mohit”, new Double(123.22));
hm.put(“Ashish”, new Double(1200.34));
hm.put(“Khariwal”, new Double(99.34));
hm.put(“Pankaj”, new Double(-19.34));
Set set = hm.entrySet();
Iterator i = set.iterator();
while(i.hasNext()){
Map.Entry me = (Map.Entry)i.next();
System.out.println(me.getKey() + “ : ” + me.getValue() );
}
//deposit into Rohit’s Account
double balance = ((Double)hm.get(“Rohit”)).doubleValue();
hm.put(“Rohit”, new Double(balance + 1000));
System.out.println(“Rohit new balance : ” + hm.get(“Rohit”));
}
}
运行后的输出如下:
Rohit : 3434.34
Ashish : 1200.34
Pankaj : -19.34
Mohit : 123.22
Khariwal : 99.34
Rohit new balance : 4434.34
一.同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的
二.数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半
就HashMap与HashTable主要从三方面来说:
一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现
二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的
三.值:只有HashMap可以让你将空值作为一个表的条目的key或value
//这是我的定时器类,用来定时执行某段任务;
package com.my.time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
public class BugXmlTimer {
public Timer timer;
public void timerStart(){
timer = new Timer();
Date datetime=new Date();
Date midnightDate=new Date();
SimpleDateFormat sdf1 = new SimpleDateFormat(“yyyy-MM-dd”);
SimpleDateFormat sdf2 = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
try {
midnightDate = sdf2.parse(sdf1.format(datetime)+” 23:00:00″);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long in=midnightDate.getTime()-datetime.getTime();
System.out.println(“before task”);
//立刻执行,然后每隔30s执行一次
timer.schedule(new BugXmlTimerTask(), 0,30000);
}
public void timerStop(){
if(timer!=null)
timer.cancel();
}
public static void main(String[] args){
BugXmlTimer myTimer=new BugXmlTimer();
// TODO Auto-generated [...]
通常我们会把事务处理放在业务层。
[1]引子
比如:
业务逻辑方法
public A bussinessMethod(){
DaoA a = new DaoA();
a.udpate();
DaoB b = new DaoB();
b.update;
}
假设,上面的事务是自动提交的。
那么,我们就可以什么不考虑。但是有一个问题,创建DAO对象的时候两个对象用的是不同的Connection对象。
再假定我们的取得连接的代码是
public Connection getConnection(String username, String password)
throws SQLException {
Connection con = DriverManager
.getConnection(conStr, username, password);
return con;
}
这个方法的一个调用。
那么如果,我们需要自己控制事务的开始和结束。
如何控制呢。
也许又有了新的方法
public A bussinessMethod(){
DaoA a = new DaoA();
a.beginTx();
a.udpate();
a.endTx();
a.close();
DaoB b = [...]
主要有三个问题:
1,struts中资源文件中如果value为中文,显示乱码
解决办法:使用eclipse插件Properties Editor
2,在文本域里输入中文显示乱码
解决办法:使用servlet过滤器filter
最简单的可以借用tomcat下面的filters.SetCharacterEncodingFilter在自己的web.xml配置中加入tomcat中servlet_examples相应配置(高手可以自己配!)
本人配置如下:
SetCharacterEncoding
filters.SetCharacterEncodingFilter
encoding
GBK
SetCharacterEncoding
*.do
3,从某些数据库里读出乱码
解决办法:把你要显示成中文的部分重新编码
例如:
while (rs.next())
{
String col1 = rs.getString(1);
String col2 = rs.getString(2);
String col3 = rs.getString(3);
float col4 = rs.getFloat(4);
//convert character encoding
col1=new String(col1.getBytes(“ISO-8859-1″),”GB2312″);
col2=new String(col2.getBytes(“ISO-8859-1″),”GB2312″);
col3=new String(col3.getBytes(“ISO-8859-1″),”GB2312″);
}
日期:2010年02月04日 | 分类:
JAVA,
学习笔记
Spring 和EJB争吵终于即将结束:Spring将支持EJB3.1标准,Spring will also be a full featured EJB 3.1 implementation for use in the WebLogic application server.这场融合将在javaEE 6实现,这个融合和当初Hibernate与JPA融合一样水到渠成。
Spring创始人Rod Johnson 说Spring 2.5的dependency injection annotations是学习得益于EJB 3.0的 @Resource 和 Google’s Guice,我不知道他为什么没有提picocontainer,至少他的Spring 2.5开始直接大胆使用DI的auto wiring(而这个功能在Spring 1.X中还是可选功能),而2005年我的Jdon框架就完全是auto wiring。
Rod Johnson 鼓励开发者使用EJB标准,比如 @PostConstruct 和 @PreDestroy annotations,因为他们是标准化的,Spring已经支持他们(Spring才支持它们?今天才明白?),这些都意味着Spring和EJB争吵的结束。
其实EJB的@PostConstruct @PreDestroy @Resource 这样annotations都可以在EJB2中找到影子和原根,表现语法不一样,但是内部机制原理是一致的。所以,以前没有学过EJB的,看来还是要补这一课。
PostConstruct和PreDestroy都是在对象生命周期开始以及结束让程序员能够进行一些状态管理,比如开始一些场景准备和加载,或者结束后,释放一些资源,防止内存泄漏,这些都是从EJB1.X 无态Bean开始就有的功能,不过当初是使用XML配置,并且无论程序员实现与否,一定要写这几个方法,现在通过注解 annotation 加在你需要实现的方法上,更加简洁方便。
所以,我以前说:如果说EJB1/EJB2X是一个定型的女孩的话;那么EJB3引入IOC/DI依赖注射和annotation以后,就更漂亮,更加吸引程序员接近她,也非常容易和其打交道了。
EJB从开始诞生起,因为高低各种原因,被高端和低端各种人怀疑打击,真正是遭受了不公平待遇,
高端专家比如Martin Fowler因为其不宜测试,提出POJO思想,认为对象应该不依赖平台,应该是一个个光溜溜来去无牵挂的,不继承任何框架接口等。不可否认POJO促进了EJB3变得更漂亮,但是EJB内在分布式计算组件的重点没有变。
在低端程序员中,EJB以其深奥的原理和超前的设计思维,更不能被他们理解,他们甚至以一种僵化思维来看:现实80%不是大系统,不需要集群分布式计算。
[...]
日期:2010年02月04日 | 分类:
JAVA,
业界动态
下述十四个技巧,是许多人在大量的数据库分析与设计实践中,逐步总结出来的。对于这些经验的运用,读者不能生帮硬套,死记硬背,而要消化理解,实事求是,灵活掌握。并逐步做到:在应用中发展,在发展中应用。
1. 原始单据与实体之间的关系
可以是一对一、一对多、多对多的关系。在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体。在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证对应多个实体,或多张原始单证对应一个实体。这里的实体可以理解为基本表。明确这种对应关系后,对我们设计录入界面大有好处。
〖例1〗:一份员工履历资料,在人力资源信息系统中,就对应三个基本表:员工基本情况表、社会关系表、工作简历表。这就是“一张原始单证对应多个实体”的典型例子。
2. 主键与外键
一般而言,一个实体不能既无主键又无外键。在E?R 图中, 处于叶子部位的实体, 可以定义主键,也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。
主键与外键的设计,在全局数据库的设计中,占有重要地位。当全局数据库的设计完成以后,有个美国数据库设计专家说:“键,到处都是键,除了键之外,什么也没有”,这就是他的数据库设计经验之谈,也反映了他对信息系统核心(数据模型)的高度抽象思想。因为:主键是实体的高度抽象,主键与外键的配对,表示实体之间的连接。
3. 基本表的性质
基本表与中间表、临时表不同,因为它具有如下四个特性:
(1) 原子性。基本表中的字段是不可再分解的。
(2) 原始性。基本表中的记录是原始数据(基础数据)的记录。
(3) 演绎性。由基本表与代码表中的数据,可以派生出所有的输出数据。
(4) 稳定性。基本表的结构是相对稳定的,表中的记录是要长期保存的。
理解基本表的性质后,在设计数据库时,就能将基本表与中间表、临时表区分开来。
4. 范式标准
基本表及其字段之间的关系, 应尽量满足第三范式。但是,满足第三范式的数据库设计,往往不是最好的设计。为了提高数据库的运行效率,常常需要降低范式标准:适当增加冗余,达到以空间换时间的目的。
〖例2〗:有一张存放商品的基本表,如表1所示。“金额”这个字段的存在,表明该表的设计不满足第三范式,因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“金额”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。
在Rose 2002中,规定列有两种类型:数据列和计算列。“金额”这样的列被称为“计算列”,而“单价”和“数量”这样的列被称为“数据列”。
表1 商品表的表结构
商品名称 商品型号 单价 数量 金额
电视机 29? 2,500 40 100,000
5. 通俗地理解三个范式
通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中,为了更好地应用三个范式,就必须通俗地理解三个范式(通俗地理解是够用的理解,并不是最科学最准确的理解):
第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;
第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余.
没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余。
6. 要善于识别与正确处理多对多的关系
若两个实体之间存在多对多的关系,则应消除这种关系。消除的办法是,在两者之间增加第三个实体。这样,原来一个多对多的关系,现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个实体中去。这里的第三个实体,实质上是一个较复杂的关系,它对应一张基本表。一般来讲,数据库设计工具不能识别多对多的关系,但能处理多对多的关系。
[...]
日期:2010年02月04日 | 分类:
JAVA,
数据库