上两篇文章中,基本的环境搭建好了,还需要写点代码测试一下是否真的好用。
1.实体类,在第二篇中,我配置了一个名为Test的hibernate实体类,下面是代码
由于纯粹是为了搭建框架,实体类很简单,test表有3个字段:id,name,test_value
@Entity
@Table(name = "test")
public class Test implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 6458575796251625995L;
// Fields
long id;
private String name;
private Long testValue;
/** default constructor */
public Test() {
}
// Property accessors
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
} public void setId(long id){
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "test_value")
public Long getTestValue() {
return testValue;
}
public void setTestValue(Long testValue) {
this.testValue = testValue;
}
}
2.dao 这个dao我就直接写成类了,没有用接口的形式。有需要的话可以把dao层写成接口,再搞一个dao的实现层。
public class TestDao{
private EntityManager em;
public TestDao(){
}
@Inject
public TestDao(EntityManager em){
this.em = em;
}
public void save(Test test){
em.persist(test);
}
public List getList(){
Query q = em.createQuery("from Test");
return q.getResultList();
}
}
dao很简单,实现了2个方法,save和getList,用于插入和查询所有数据,使用标准jpa编码方式。关键点是构造方法,一个无参数构造方法,这是必须的;一个是包含EntityManager 参数的构造方法,并且使用guice的@Inject进行注入。这个EntityManager 是由guice管理的,不需要我们做其他的事。
3.创建服务
下面我们创建一个服务接口用与调用dao层的方法,与spring标准的service层概念相同:
import java.util.List;
import com.google.inject.ImplementedBy;
import com.test.serviceimpl.TestImpl;
import com.test.vo.Test;
@ImplementedBy(TestImpl.class)
public interface TestService {
void saveObject(Test test);
List getList();
}
为了简单,与dao层方法是对应的。@ImplementedBy(TestImpl.class)这个注解是关键,即告诉guice这个接口的实现类是com.test.serviceimpl.TestImpl。guice就这么简单!下面是TestImpl的代码:
import java.util.List;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import com.test.dao.TestDao;
import com.test.service.TestService;
import com.test.vo.Test;
public class TestImpl implements TestService {
@Inject
private TestDao testDao;
@Transactional
@Override
public void saveObject(Test test) {
testDao.save(test);
}
public List getList(){
return testDao.getList();
}
}
@Inject注入了testDao这个bean。@Transactional标识方法需要事务控制。
jpa的基本代码就编写完成了,用action测试一下:
插入数据的action
import com.google.inject.Inject;
import com.test.service.TestService;
import com.test.vo.Test;
public class SaveAction {
@Inject
private TestService testService;
public String execute() {
Test test = new Test();
test.setName("nameguice");
test.setTestValue(1025L);
testService.saveObject(test);
return "success";
}
}
获取数据的action:
import java.util.List;
import com.google.inject.Inject;
import com.test.service.TestService;
import com.test.vo.Test;
public class ListAction {
@Inject
private TestService testService;
public String execute() {
List<Test> l = testService.getList();
String s = "";
for(int i=0;i<l.size();i++){
s += l.get(i).getName();
}
System.out.println(s);
return "success";
}
}
我自己测试的情况比较满意,事务能够正常提交,而且不会锁死数据源。
配置过程中,出现了不少问题,多数还是自己没有仔细阅读官方文档导致的,也因为英语不那么灵光,多少感觉有点读起来费劲。下面列几个我遇到的主要问题,希望其他人少走弯路。
1.ServletContextListener里面,没有把install(new JpaPersistModule("unit1"));放到第一个,虽然系统启动成功,但是写入数据库的时候没有提交到数据库,手动执行flush()方法报了一个没有事务的错误。人家官方userguide写的很明白要靠前放,自己疏忽了。
2.jpa配置文件,我习惯性的放到了WebRoot/META-INF里面了,启动时报unit1和这个东西找不到,让我足足搞了好几个小时。日志里面其实在报错之前也输出了persistence.xml没找到的信息,只是我太着急没有看到。
3.TestDao类让我加了个@Singleton注解,导致提交不了,也没生成insert语句,userguide里面明确说如果是Singleton,那注入的话,要用Provider方式。最后我去掉了Singleton就可以插入数据了
4.userguide里面写了如何整合strtus,最后还写了之前版本guice如何整合,结果没注意那个“之前版本”,把那个guice的配置直接粘贴到了stutus.xml中了,导致启动失败。实际上目前版本与整合servlet一样,直接使用那个listener就可以了。
关于这个环境的配置,包括guice的学习,我也就搞了2天,所以很多地方理解的不够深刻,有能人希望能指点一下。