上兩篇文章中,基本的環境搭建好了,還需要寫點代碼測試一下是否真的好用。
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天,所以很多地方理解的不夠深刻,有能人希望能指點一下。