要實現CRUD,首先需要完成DAO這塊coding,之後再搭配表單與Controller來進行相關操作,資料庫選擇MySQL,ORM部分選用Hibernate/JPA(Java Persistence API),今天要分享Hibernate/JPA Java Config Class如何撰寫,首先加入相關的Dependency(Springframework ORM及Hibernate)於pom.xml
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
....
<properties>
<hibernate.version>4.3.6.Final</hibernate.version>
<spring.version>4.0.7.RELEASE</spring.version>
...
</properties>
接著新增一 POJO並使用JPA Annotation,有人習慣將Annotation放在getter的地方,有人放在屬性(field)的地方,看個人習慣。
@Entity
//預設Table name即為class name, 如果要指定table name,則需加入@Table(name="tablename")
public class DCN implements Serializable{
private static final long serialVersionUID = 3716247587694820755L;
public DCN(){
}
@Id //@Id代表這個屬性是primary key
@GeneratedValue(generator="uuid")//新增一筆資料時產生key的方法,或稱為generator
@GenericGenerator(name="uuid", strategy="uuid")//指定uuid演算法產生primary key
private String prikey;
@Column //@Column代表屬性要persist到資料庫,預設資料庫欄位名稱就是該變數
private String category;
private Integer serialNumber;
@Column(name="no") //也可以另外指定資料庫實際欄位名稱
private String no;
private Integer rev;
@Column
private String issueDate;
@Column
private String completedDate;
@Transient //代表此屬性不persist到資料庫
private MultipartFile uploadFile;
//getter以及setter省略
}
接著refactor之前的ServiceConfig為PersistenceConfig,裡面已經有Datasource,記得把database的url、username及password寫入jdbc.properties檔,在Spring專案要導入JPA,我們需要org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean來設定Entity Manager Factory(對應到Hibernate的Session Factory)相關參數,如指定Hibernate為實作JPA的Provider,同時我們也需要org.springframework.transaction.PlatformTransactionManager來管理Transaction,相關Bean Code如下
package tw.blogger.springtech.springmvc.config;
import javax.persistence.EntityManagerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.jolbox.bonecp.BoneCPDataSource;
@PropertySource(value="classpath:jdbc.properties")
@EnableTransactionManagement
@Configuration
public class PersistenceConfig {
@Autowired
Environment env; //Environment物件存放Profile以及Property Source
@Bean
public BoneCPDataSource dataSource(){
BoneCPDataSource datasource = new BoneCPDataSource();
/*以下就設定一些dataSource的參數,url, username及password key/value pair
* 另外存在jdbc.properties檔裡,再用eng.getProperty("key")取得value,
*/
datasource.setDriverClass("com.mysql.jdbc.Driver");
datasource.setJdbcUrl(env.getProperty("jdbc.url"));
datasource.setUsername(env.getProperty("jdbc.username"));
datasource.setPassword(env.getProperty("jdbc.password"));
datasource.setIdleConnectionTestPeriodInMinutes(60);
datasource.setIdleMaxAgeInMinutes(420);
datasource.setMaxConnectionsPerPartition(30);
datasource.setMinConnectionsPerPartition(10);
datasource.setPartitionCount(3);
datasource.setAcquireIncrement(5);
datasource.setStatementsCacheSize(100);
return datasource;
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(dataSource()); //Dependency Injection只需要呼叫方法即可
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
//new 一個entity factory
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();//new一個實作JPA的vendor
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(true); //設定showSQL
factory.setDataSource(dataSource()); //設定datasource
factory.setJpaVendorAdapter(vendorAdapter); //設定Implement JPA vendor
factory.setPackagesToScan("tw.blogger.springtech.springmvc.model"); //設定Entity package位置
factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
return factory;
}
@Bean
public PlatformTransactionManager transactionManager(){
EntityManagerFactory factory = entityManagerFactory().getObject();
return new JpaTransactionManager(factory);
//JpaTransactionManager需要注入EntityManagerFactory的Instance
}
@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator(){
return new HibernateExceptionTranslator();
}
}
今天先到這邊,明天再進行後續分享,這邊以後可能會稍微慢一點,JPA相關我也是邊看邊學(本來就夠慢了嗎!?)。