我们可以通过纯JDBC进行数据库操作,也可以通过Spring封装的JdbcTemplate,或者用其他第三方ORM工具,如Hibernate、iBatis等;
这里介绍一种简便的方式:Spring-Data-JPA + Hibernate实现
此方式基于标准JPA规范定义了数据持久化时Java模型和表之间的映射关系,使用Spring-Data-JPA提供的数据访问接口,以及Hibernate实现,来完成数据库的操作;
因此在使用时,主要工作是模型映射、以及数据访问接口申明,接口如何实现,由Spring代理生成;
下面先提供一个样例,来简要说明如何使用JPA来完成数据的访问;
工程结构
AlarmTrace
|--src/main/java
|--com.boco.alarmTrace.dao.jpa
|--RecDao.java
|--entity
|--CommonEntity.java
|--TfaAlgRec.java
|--src/main/resource
|--spring-jpa.xml
|--src/test/java
|--com.boco.alarmTrace.dao
|--RecDaoTest.java
在maven工程中,需要引入下面jar依赖
<!-- Spring org.springframework-version=4.0.3.RELEASE -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework-version}</version>
<scope>compile</scope>
</dependency>
<!-- jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.3</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.0.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.7.0.RELEASE</version>
</dependency>
DAO接口申明
首先看DAO的定义 -- RecDao.java
package com.boco.alarmTrace.dao.jpa;
import java.sql.Timestamp;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.boco.alarmTrace.dao.jpa.entity.TfaAlgRec;
/**
* 通过操作模型TfaAlgRec来操作表tfa_alg_rec;
* <p>
* 此接口继承spring的JpaRepository,可以不用自己实现,就能操作数据表;
* 因为接口JpaRepository在加载时,spring会动态代理生成其实现;
*
* <pre>
* JpaRepository接口继承关系如下
* Repository {Spring Data 的一个核心接口,它不提供任何方法}
* |--CrudRepository
* |--PagingAndSortingRepository
* |--JpaRepository
*
* Repository Spring Data 的一个核心接口,它不提供任何方法
* CrudRepository 提供增删改查方法
* PagingAndSortingRepository 提供分页查询和排序是持久层常用的功能
* JpaRepository 针对 JPA 技术提供的接口,它在父接口的基础上,提供了其他一些方法,比如 flush(),saveAndFlush(),deleteInBatch() 等
* </pre>
*
* <pre>
* Spring Data JPA 在后台为持久层接口创建代理对象时,会解析方法名字,并实现相应的功能。除了通过方法名字以外,它还可以通过如下两种方式指定查询语句:
* Spring Data JPA 可以访问 JPA 命名查询语句。开发者只需要在定义命名查询语句时,为其指定一个符合给定格式的名字,Spring Data JPA 便会在创建代理对象时,使用该命名查询语句来实现其功能。
* 开发者还可以直接在声明的方法上面使用{@code @Query} 注解,并提供一个查询语句作为参数,Spring Data JPA 在创建代理对象时,便以提供的查询语句来实现其功能。
*
* </pre>
*
* @author DAL.feng
*/
//@Repository("recDao")
public interface RecDao extends JpaRepository<TfaAlgRec, Integer>, MyJpaDao {
/**
* <p>
* 使用 -@Query 创建查询
* </p>
*
* 通过自己设置查询语句,来完成数据访问;<br>
* select tfaalgrec0_.id as id1_0_, tfaalgrec0_.alarm_severity as alarm_se2_0_, tfaalgrec0_.alarm_title_text as alarm_ti3_0_, tfaalgrec0_.cfp0 as cfp4_0_, tfaalgrec0_.cfp1 as cfp5_0_, tfaalgrec0_.cfp2 as cfp6_0_, tfaalgrec0_.cfp3 as cfp7_0_, tfaalgrec0_.fp0 as fp8_0_, tfaalgrec0_.fp1 as fp9_0_, tfaalgrec0_.fp2 as fp10_0_, tfaalgrec0_.fp3 as fp11_0_, tfaalgrec0_.ins_time as ins_tim12_0_, tfaalgrec0_.model_id as model_i13_0_, tfaalgrec0_.msg_serail as msg_ser14_0_, tfaalgrec0_.operate_unite as operate15_0_, tfaalgrec0_.rec_time as rec_tim16_0_, tfaalgrec0_.sc_time as sc_time17_0_, tfaalgrec0_.send_time as send_ti18_0_, tfaalgrec0_.special_id as special19_0_, tfaalgrec0_.status as status20_0_
* from tfa_alg_rec tfaalgrec0_
* where tfaalgrec0_.fp0=? and tfaalgrec0_.fp1=? and tfaalgrec0_.fp2=? and tfaalgrec0_.fp3=? and tfaalgrec0_.model_id=? and (tfaalgrec0_.sc_time between ? and ?)
*
* <p>
* 注意:
* 此sql可以是JPQL,基于映射后的模型对象查询,也可以是原生sql,如果是原生sql,则必须指定Query属性nativeQuery=true
* </p>
*
* <pre>
* -@Query注解的使用非常简单,只需在声明的方法上面标注该注解,同时提供一个 JPQL 查询语句即可,如下所示:
* {@code
* public interface UserDao extends Repository<AccountInfo, Long> {
*
* public AccountInfo save(AccountInfo accountInfo);
*
* @Query("from AccountInfo a where a.accountId = :id")
* public AccountInfo findByAccountId(@Param("id")Long accountId);
*
* @Query("from AccountInfo a where a.balance > :balance")
* public Page<AccountInfo> findByBalanceGreaterThan(@Param("balance")Integer balance,Pageable pageable);
* }
* }
*
* 此外,开发者也可以通过使用-@Query来执行一个更新操作,为此,我们需要在使用-@Query的同时,用-@Modifying来将该操作标识为修改查询,这样框架最终会生成一个更新的操作,而非查询。如下所示:
* {@code
* @Modifying
* @Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2")
* public int increaseSalary(int after, int before);
* }
*
* </pre>
*
* @param fp0
* @param fp1
* @param fp2
* @param fp3
* @param modelId
* @param startTime
* @param endTime
* @return
*/
@Query(value="from TfaAlgRec rec where rec.fp0=:fp0 and rec.fp1=:fp1 and rec.fp2=:fp2 and rec.fp3=:fp3 and rec.modelId=:modelId and rec.scTime between :startTime and :endTime")
public List<TfaAlgRec> findByFp(@Param("fp0")long fp0, @Param("fp1")long fp1, @Param("fp2")long fp2, @Param("fp3")long fp3, @Param("modelId")int modelId, @Param("startTime")Timestamp startTime, @Param("endTime")Timestamp endTime);
/**
* <p>
* 通过解析方法名创建查询
* </p>
*
* 通过代理生成其实现方法,最后拼接的sql样例如下:<br>
* select tfaalgrec0_.id as id1_0_, tfaalgrec0_.alarm_severity as alarm_se2_0_, tfaalgrec0_.alarm_title_text as alarm_ti3_0_, tfaalgrec0_.cfp0 as cfp4_0_, tfaalgrec0_.cfp1 as cfp5_0_, tfaalgrec0_.cfp2 as cfp6_0_, tfaalgrec0_.cfp3 as cfp7_0_, tfaalgrec0_.fp0 as fp8_0_, tfaalgrec0_.fp1 as fp9_0_, tfaalgrec0_.fp2 as fp10_0_, tfaalgrec0_.fp3 as fp11_0_, tfaalgrec0_.ins_time as ins_tim12_0_, tfaalgrec0_.model_id as model_i13_0_, tfaalgrec0_.msg_serail as msg_ser14_0_, tfaalgrec0_.operate_unite as operate15_0_, tfaalgrec0_.rec_time as rec_tim16_0_, tfaalgrec0_.sc_time as sc_time17_0_, tfaalgrec0_.send_time as send_ti18_0_, tfaalgrec0_.special_id as special19_0_, tfaalgrec0_.status as status20_0_
* from tfa_alg_rec tfaalgrec0_
* where tfaalgrec0_.fp0=? and tfaalgrec0_.fp1=? and tfaalgrec0_.fp2=? and tfaalgrec0_.fp3=?
*
* <pre>
* 在代理生成实现时,实际是先解析接口中的方法名,其逻辑如下:
*
* 框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如 find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是 Sort 或者 Pageable 类型,也会提取相关的信息,以便按规则进行排序或者分页查询。
* 在创建查询时,我们通过在方法名中使用属性名称来表达,比如 findByUserAddressZip()。框架在解析该方法时,首先剔除 findBy,然后对剩下的属性进行解析,详细规则如下(此处假设该方法针对的域对象为 AccountInfo 类型):
*
* <li>先判断 userAddressZip (根据 POJO 规范,首字母变为小写,下同)是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;</li>
* <li>从右往左截取第一个大写字母开头的字符串(此处为 Zip),然后检查剩下的字符串是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 user 为 AccountInfo 的一个属性;</li>
* <li>接着处理剩下部分( AddressZip ),先判断 user 所对应的类型是否有 addressZip 属性,如果有,则表示该方法最终是根据 "AccountInfo.user.addressZip" 的取值进行查询;否则继续按照步骤 2 的规则从右往左截取,最终表示根据 "AccountInfo.user.address.zip" 的值进行查询。</li>
*
* 可能会存在一种特殊情况,比如 AccountInfo 包含一个 user 的属性,也有一个 userAddress 属性,此时会存在混淆。读者可以明确在属性之间加上 "_" 以显式表达意图,比如 "findByUser_AddressZip()" 或者 "findByUserAddress_Zip()"。
* 在查询时,通常需要同时根据多个属性进行查询,且查询的条件也格式各样(大于某个值、在某个范围等等),Spring Data JPA 为此提供了一些表达条件查询的关键字,大致如下:
* And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
* Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
* Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
* LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
* GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
* IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();
* IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
* NotNull --- 与 IsNotNull 等价;
* Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);
* NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
* OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
* Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);
* In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
* NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
* </pre>
*
* @param fp0
* @param fp1
* @param fp2
* @param fp3
* @return
*/
public List<TfaAlgRec> findByFp0AndFp1AndFp2AndFp3(long fp0, long fp1, long fp2, long fp3);
@Query("from TfaAlgRec rec where rec.cfp0=:cfp0 and rec.cfp1=:cfp1 and rec.cfp2=:cfp2 and rec.cfp3=:cfp3 and rec.modelId=:modelId and rec.scTime between :startTime and :endTime")
public List<TfaAlgRec> findByCfp(@Param("cfp0")long cfp0, @Param("cfp1")long cfp1, @Param("cfp2")long cfp2, @Param("cfp3")long cfp3, @Param("modelId")int modelId, @Param("startTime")Timestamp startTime, @Param("endTime")Timestamp endTime);
public List<TfaAlgRec> findByMsgSerail(String msgSerail);
@Query("from TfaAlgRec rec where rec.modelId=:modelId and rec.scTime between :startTime and :endTime")
public List<TfaAlgRec> findByModleidAndSctime(@Param("modelId")int modelId, @Param("startTime")Timestamp startTime, @Param("endTime")Timestamp endTime);
}
模型映射
本java接口中,定义了几个数据访问方法,以及继承的
JpaRepository
方法,会在spring加载时,自动
代理
生成其实现类;
该接口中,绑定了模型映射TfaAlgRec,此类定义如下
package com.boco.alarmTrace.dao.jpa.entity;
import java.sql.Timestamp;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
* 定义对象模型和表字段的映射关系<br>
*
* 通过JPA标准规范定义,采用Spring Data JPA实现,需要在pom中引入spring(4.0.3.RELEASE)、hibernate(4.3.1.Final),还需要
* <pre>
* {@code
* <dependency>
* <groupId>org.springframework.data</groupId>
* <artifactId>spring-data-jpa</artifactId>
* <version>1.7.0.RELEASE</version>
* </dependency>
* <dependency>
* <groupId>org.hibernate</groupId>
* <artifactId>hibernate-entitymanager</artifactId>
* <version>4.3.0.Final</version>
* </dependency>
* }
* </pre>
* <pre>
* spring-data-jpa
* |--spring-jpa.xml jpa申明及持久化配置(此配置可去掉persistence.xml)
* |--*Dao 数据访问接口申明,接口方法遵循一定规则,自己不需要实现,由spring代理实现
* |--TfaAlg* 表和对象模型映射定义
* </pre>
*
* @author DAL.feng
*/
@Entity
@Table(name="tfa_alg_rec")
public class TfaAlgRec extends CommonEntity {
private static final long serialVersionUID = 1L;
/**
* Id:标注表中pk属性,且表中id字段映射到对象属性id上
*/
// @Id
private Integer id;
/** 告警唯一标识 */
private String msgSerail;
/** 告警状态 */
private int status;
/**
* 将表中字段fp0映射到对象属性fp0
*/
private long fp0;
private long fp1;
private long fp2;
private long fp3;
private long cfp0;
private long cfp1;
private long cfp2;
private long cfp3;
/** 产生模块 */
private Integer modelId;
/** 处理单元 */
private String operateUnite;
/** 特殊ID 消息平台filterid、gtft和gaia是ruleid */
private Integer specialId;
/** 入库时间 */
private Timestamp insTime;
/** 告警采集接收产生时间 */
private Timestamp scTime;
/** 模块接收时间 */
private Timestamp recTime;
/** 模块发送时间 */
private Timestamp sendTime;
/** 告警标题 */
private String alarmTitleText;
/** 告警级别 */
private String alarmSeverity;
/**
* 用于申明和表中字段无映射关系的对象属性
*/
// @Transient
// private long curTime;
// getter and setter
/**
* Id:标注表中pk属性,且表中id字段映射到对象属性id上
* 将persistence.xml去掉后,采用自动扫描,需要将Id注解放到get方法上
*/
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
/**
* 将表中字段msg_serail映射到对象属性msgSerail,并限制长度为24,且入库时值不能为空
*/
@Column(name="msg_serail", length=24, nullable=true)
public String getMsgSerail() {
return msgSerail;
}
public void setMsgSerail(String msgSerail) {
this.msgSerail = msgSerail;
}
@Column(name="status")
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public long getFp0() {
return fp0;
}
public void setFp0(long fp0) {
this.fp0 = fp0;
}
public long getFp1() {
return fp1;
}
public void setFp1(long fp1) {
this.fp1 = fp1;
}
public long getFp2() {
return fp2;
}
public void setFp2(long fp2) {
this.fp2 = fp2;
}
public long getFp3() {
return fp3;
}
public void setFp3(long fp3) {
this.fp3 = fp3;
}
public long getCfp0() {
return cfp0;
}
public void setCfp0(long cfp0) {
this.cfp0 = cfp0;
}
public long getCfp1() {
return cfp1;
}
public void setCfp1(long cfp1) {
this.cfp1 = cfp1;
}
public long getCfp2() {
return cfp2;
}
public void setCfp2(long cfp2) {
this.cfp2 = cfp2;
}
public long getCfp3() {
return cfp3;
}
public void setCfp3(long cfp3) {
this.cfp3 = cfp3;
}
@Column(name="model_id", nullable=true)
public Integer getModelId() {
return modelId;
}
public void setModelId(Integer modelId) {
this.modelId = modelId;
}
@Column(name="operate_unite", length=255, nullable=true)
public String getOperateUnite() {
return returnEmptyIfNull(operateUnite);
}
public void setOperateUnite(String operateUnite) {
this.operateUnite = operateUnite;
}
@Column(name="special_id")
public Integer getSpecialId() {
return specialId;
}
public void setSpecialId(Integer specialId) {
this.specialId = specialId;
}
@Column(name="ins_time")
public Timestamp getInsTime() {
return insTime;
}
public void setInsTime(Timestamp insTime) {
this.insTime = insTime;
}
public void setInsTime(String insTime) {
this.insTime = changeStrTimeToTimestamp(insTime);
}
@Column(name="sc_time")
public Timestamp getScTime() {
return scTime;
}
public void setScTime(Timestamp scTime) {
this.scTime = scTime;
}
public void setScTime(String scTime) {
this.scTime = changeStrTimeToTimestamp(scTime);
}
@Column(name="rec_time")
public Timestamp getRecTime() {
return recTime;
}
public void setRecTime(Timestamp recTime) {
this.recTime = recTime;
}
public void setRecTime(String recTime) {
this.recTime = changeStrTimeToTimestamp(recTime);
}
@Column(name="send_time")
public Timestamp getSendTime() {
return sendTime;
}
public void setSendTime(Timestamp sendTime) {
this.sendTime = sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = changeStrTimeToTimestamp(sendTime);
}
@Column(name="alarm_title_text", length=255)
public String getAlarmTitleText() {
return returnEmptyIfNull(alarmTitleText);
}
public void setAlarmTitleText(String alarmTitleText) {
this.alarmTitleText = alarmTitleText;
}
@Column(name="alarm_severity", length=64)
public String getAlarmSeverity() {
return returnEmptyIfNull(alarmSeverity);
}
public void setAlarmSeverity(String alarmSeverity) {
this.alarmSeverity = alarmSeverity;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("TfaAlgRec [id=");
builder.append(id);
builder.append(", msgSerail=");
builder.append(msgSerail);
builder.append(", status=");
builder.append(status);
builder.append(", fp0=");
builder.append(fp0);
builder.append(", fp1=");
builder.append(fp1);
builder.append(", fp2=");
builder.append(fp2);
builder.append(", fp3=");
builder.append(fp3);
builder.append(", cfp0=");
builder.append(cfp0);
builder.append(", cfp1=");
builder.append(cfp1);
builder.append(", cfp2=");
builder.append(cfp2);
builder.append(", cfp3=");
builder.append(cfp3);
builder.append(", modelId=");
builder.append(modelId);
builder.append(", operateUnite=");
builder.append(operateUnite);
builder.append(", specialId=");
builder.append(specialId);
builder.append(", insTime=");
builder.append(insTime);
builder.append(", scTime=");
builder.append(scTime);
builder.append(", recTime=");
builder.append(recTime);
builder.append(", sendTime=");
builder.append(sendTime);
builder.append(", alarmTitleText=");
builder.append(alarmTitleText);
builder.append(", alarmSeverity=");
builder.append(alarmSeverity);
builder.append("]");
return builder.toString();
}
@Transient
@Override
public String insertSql() {
return "insert into tfa_alg_rec (alarm_severity, alarm_title_text, cfp0, cfp1, cfp2, cfp3, "
+ "fp0, fp1, fp2, fp3, ins_time, model_id, msg_serail, operate_unite, rec_time, "
+ "sc_time, send_time, special_id, status, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
}
@Transient
@Override
public Object[] getParams() {
return new Object[] {
getAlarmSeverity(),
getAlarmTitleText(),
getCfp0(),
getCfp1(),
getCfp2(),
getCfp3(),
getFp0(),
getFp1(),
getFp2(),
getFp3(),
getInsTime(),
getModelId(),
getMsgSerail(),
getOperateUnite(),
getRecTime(),
getScTime(),
getSendTime(),
getSpecialId(),
getStatus(),
getId()
};
}
}
package com.boco.alarmTrace.dao.jpa.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
public abstract class CommonEntity implements Serializable {
private static final long serialVersionUID = 341339020055925890L;
public static final String EMPTY_VALUE_DEFAULT = "";
public static final Timestamp TIMESTAMP_NULL = null;
protected SimpleDateFormat dateToSecondFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public abstract String insertSql();
public abstract Object[] getParams();
/**
* 检测传入的字符串是否为空,如果为空,则返回默认的空字符串""
*
* @param val 被检测的字符串,为空的判断条件:字符串==nul,或者字符串.trim()=""
* @return 字符串为空返回"",否则返回传入的字符串
*/
public String returnEmptyIfNull(String val) {
if(StringUtils.isBlank(val)) {
return EMPTY_VALUE_DEFAULT;
} else {
return val;
}
}
/**
* 检测时间类型变量是否为空,如果为空,则返回默认空字符串"",否则返回经yyyy-MM-dd HH:mm:ss转换后的文本时间
* @param val
* @return
*/
public String returnEmptyIfNull(Timestamp val) {
if(val == null) {
return EMPTY_VALUE_DEFAULT;
}
return dateToSecondFormat.format(new Date(val.getTime()));
}
/**
* 将yyyy-MM-dd HH:mm:ss文本型时间,转换成格林威治时间
* @param timeStr
* @return
*/
public Timestamp changeStrTimeToTimestamp(String timeStr) {
try {
return new Timestamp(dateToSecondFormat.parse(timeStr).getTime());
} catch (ParseException e) {
return TIMESTAMP_NULL;
}
}
}
spring配置
模型映射、DAO声明都已完成,接下来是spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.8.xsd">
<context:component-scan base-package="com.boco.alarmTrace.service.jpa"/>
<!--
<tx:annotation-driven transaction-manager="transactionManager"/>
<jpa:repositories base-package="footmark.springdata.jpa.dao" repository-impl-postfix="Impl" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/>
-->
<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.informix.jdbc.IfxDriver" />
<property name="url" value="jdbc:informix-sqli://10.10.1.52:8001/nmosdb:INFORMIXSERVER=nrmsserver;DELIMIDENT=y;informixserver=nrmsserver;newcodeset=gbk,cp1252,819;" />
<property name="username" value="informix" />
<property name="password" value="informix000" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds" />
</bean>
<!-- 扫描Repository及其子接口,用于生成代理实现 -->
<jpa:repositories base-package="com.boco.alarmTrace.dao.jpa"
repository-impl-postfix="Impl" entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager" />
<!--
<jpa:repository id="myJpaDao" repository-impl-ref="myJpaDaoImpl" />
<bean id="myJpaDaoImpl" class="com.boco.alarmTrace.dao.jpa.MyJpaDaoImpl">
<property name="jdbc" ref="jdbcTemplate" />
</bean>
-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="ds" />
<property name="persistenceUnitName" value="spring-jpa"/>
<!-- 扫描模型和表的映射类,用于持久化 -->
<property name="packagesToScan" value="com.boco.alarmTrace.dao.jpa.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false"/>
<property name="showSql" value="true"/>
</bean>
</property>
<!--
下面配置就不需要再配置src/META-INF/persistence.xml ${hibernate.dialect}
http://www.cnblogs.com/taven/archive/2013/10/04/3351841.html
-->
<property name="jpaProperties">
<props>
<prop key="hibernate.c3p0.min_size">50</prop>
<prop key="hibernate.hbm2ddl.auto">true</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.InformixDialect</prop>
</props>
</property>
</bean>
</beans>
测试及结果
最后,测试JPA是否好用,运行测试及结果
package com.boco.alarmTrace.dao;
import static org.junit.Assert.fail;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.boco.alarmTrace.dao.jpa.RecDao;
import com.boco.alarmTrace.dao.jpa.entity.TfaAlgRec;
public class RecDaoTest {
ApplicationContext ctx = null;
RecDao dao = null;
@Before
public void setUp() throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-jpa.xml");
dao = ctx.getBean("recDao", RecDao.class);
}
@After
public void tearDown() {
// ctx.
}
/**
* 测试DAO接口在spring初始化后是否能自动生成实现
*/
@Test
public void testDaoIsNull() {
Assert.assertNotNull(dao);
}
/**
* 测试接口方法
* <pre>
* 表中记录
* TfaAlgRec [id=4994287, msgSerail=##0QP01l0000000D543F6F11, status=1, fp0=1399144828, fp1=819453314, fp2=2286674142, fp3=1448780389, cfp0=2992234056, cfp1=3657354290, cfp2=3986893009, cfp3=2088807446, modelId=20001, operateUnite=108125-111, specialId=null, insTime=null, scTime=2014-10-16 15:09:05.0, recTime=2014-10-16 15:09:05.768, sendTime=2014-10-16 15:09:05.774, alarmTitleText=null, alarmSeverity=故障警告]
* </pre>
*/
@Test
public void testFindByFp() {
try {
System.out.println("000000000");
String sTime = "2014-10-16 15:00:00";
String eTime = "2014-10-16 15:59:59";
TfaAlgRec entity = new TfaAlgRec();
entity.setFp0(1399144828);
entity.setFp1(819453314);
entity.setFp2(2286674142l);
entity.setFp3(1448780389);
entity.setModelId(ModelDict.MODEL_RT);
Timestamp startTime = entity.changeStrTimeToTimestamp(sTime);
Timestamp endTime = entity.changeStrTimeToTimestamp(eTime);
List<TfaAlgRec> l = dao.findByFp(entity.getFp0(), entity.getFp1(), entity.getFp2(), entity.getFp3(),
entity.getModelId(), startTime, endTime);
System.out.println("l " + (l==null || l.isEmpty()));
System.out.println(l);
Assert.assertEquals(l.get(0).getFp0(), 1399144828);
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* 测试接口方法
* <pre>
* 表中记录
* TfaAlgRec [id=4994287, msgSerail=##0QP01l0000000D543F6F11, status=1, fp0=1399144828, fp1=819453314, fp2=2286674142, fp3=1448780389, cfp0=2992234056, cfp1=3657354290, cfp2=3986893009, cfp3=2088807446, modelId=20001, operateUnite=108125-111, specialId=null, insTime=null, scTime=2014-10-16 15:09:05.0, recTime=2014-10-16 15:09:05.768, sendTime=2014-10-16 15:09:05.774, alarmTitleText=null, alarmSeverity=故障警告]
* </pre>
*/
@Test
public void testFindByFp0AndFp2AndFp2AndFp3() {
TfaAlgRec entity = new TfaAlgRec();
entity.setFp0(1399144828);
entity.setFp1(819453314);
entity.setFp2(2286674142l);
entity.setFp3(1448780389);
List<TfaAlgRec> l = dao.findByFp0AndFp1AndFp2AndFp3(entity.getFp0(), entity.getFp1(), entity.getFp2(), entity.getFp3());
System.out.println("l " + (l==null || l.isEmpty()));
System.out.println(l);
Assert.assertEquals(l.get(0).getFp0(), 1399144828);
}
/**
* 测试接口方法
* <pre>
* 表中记录
* TfaAlgRec [id=4994287, msgSerail=##0QP01l0000000D543F6F11, status=1, fp0=1399144828, fp1=819453314, fp2=2286674142, fp3=1448780389, cfp0=2992234056, cfp1=3657354290, cfp2=3986893009, cfp3=2088807446, modelId=20001, operateUnite=108125-111, specialId=null, insTime=null, scTime=2014-10-16 15:09:05.0, recTime=2014-10-16 15:09:05.768, sendTime=2014-10-16 15:09:05.774, alarmTitleText=null, alarmSeverity=故障警告]
* </pre>
*/
@Test
public void testFindByCfp() {
System.out.println("------- " + (dao==null));
TfaAlgRec entity = new TfaAlgRec();
Timestamp sTime = entity.changeStrTimeToTimestamp("2014-10-16 15:00:00");
Timestamp eTime = entity.changeStrTimeToTimestamp("2014-10-16 15:59:59");
List<TfaAlgRec> l = dao.findByCfp(2992234056l, 3657354290l, 3986893009l, 2088807446l, 20001, sTime, eTime);
Assert.assertEquals(l.get(0).getCfp0(), 2992234056l);
}
@Test
public void testFindByMsgSerail() {
// fail("Not yet implemented");
}
@Test
public void testFindByModleidAndSctime() {
// fail("Not yet implemented");
}
}
测试用例运行结构