目录
在众多的orm框架中 ,mybatis 和 jpa 是我很喜欢的两个框架,我们试着将 mybatis和jpa 同时 引入到 工程中,mybatis负责复杂查询,jpa负责基本的crud 和排序分页之类的
底层建表规范
数据库是 mysql
create table T_DEMO_SAMPLE
(
ID bigint(20) not null auto_increment comment 'ID',
SAMPLE_CODE varchar(40) not null comment '示例编码',
SAMPLE_NAME varchar(100) not null comment '示例名称',
UPDATE_USER bigint(20) comment '更新者',
UPDATE_TIME timestamp not null default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
CREATE_USER bigint(20) comment '创建者',
CREATE_TIME timestamp not null default CURRENT_TIMESTAMP comment '创建时间',
LOGIC_DELETE char(1) not null default '0' comment '逻辑删除:0-未删除 1-已删除',
primary key (ID)
);
所有表都必须 id 是默认主键,creat_user —直接是存储的 user的主键id , 逻辑删除 和 业务状态 ,业务删除 一般也是必须有,
所以 我针对这几个 属性有一个 basePo,并且 这个 basePo 被所有的Po所继承
基本 po
@MappedSuperclass
public class UnexBasePo{
// ID
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// 创建者
@Column(name = "CREATE_USER")
private Long createUser;
// 创建时间
private Date createTime;
// 更新者
@Column(name = "UPDATE_USER")
private Long updateUser;
// 更新时间
private Date updateTime;
// 逻辑删除: 0-未删除 1-已删除
private String logicDelete;
基本操作
针对这几个 基本的属性,我需要 进行基本的 crud 操作,
: 1。根据 entity对象中的非空字段值查询 单条记录
2。根据 entity对象中的非空字段值查询 全部记录
@NoRepositoryBean
public interface IUnexBaseRepository<Po extends UnexBasePo> extends PagingAndSortingRepository<Po, Long> {
Po findByCondition(Po entity);
<T> List<T> queryByCondition(Po entity, Class<T> requiredType);
}
实现类
public class UnexBaseDalImpl<Po extends UnexBasePo> extends SimpleJpaRepository<Po, Long> implements IUnexBaseRepository<Po> {
private final JpaEntityInformation<Po, ?> entityInformation;
private final EntityManager em;
// 构造函数
public UnexBaseDalImpl(Class<Po> domainClass, EntityManager em) { this(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em);
}
// 逻辑删除
@Override
@Transactional
public void logicDelete(Long id) {
Assert.notNull(id, "The given id must not be null!");
Po po = findOne(id);
if (po == null) {
throw new UnexDalException(String.format("No %s entity with id %s exists!", entityInformation.getJavaType(), id));
} po.setLogicDelete(DalConstants.LOGIC_DELETE_TRUE);
po.setUpdateTime(DateUtil.now());
super.save(po);
}
// 基本的查询
@Override
public Po findOne(Long id) {
return super.findOne(id);
}
// 物理删除
@Override
@Transactional
public void delete(Long id) {
super.delete(id);
}
// 查询
@Override
@SuppressWarnings("unchecked")
public <T> T findByCondition(Po entity, Class<T> requiredType) {
Map<String, Object> params = new HashMap<String, Object>();
String querySql = UnexSqlUtil.sql_queryByCondition(entity, params);
if (logger.isDebugEnabled()) {
logger.debug("findByCondition SQL: [" + querySql + "]");
logger.debug("findByCondition PARAM:" + JSON.toJSONString(params));
}
Query query = em.createNativeQuery(querySql, requiredType);
query.setFirstResult(0);
query.setMaxResults(1);
this.setQueryParameters(query, params);
List<T> resultList = query.getResultList();
return CollectionUtils.isEmpty(resultList) ? null : resultList.get(0);
}
// 为sql查询绑定查询参数
private void setQueryParameters(Query query, Map<String, Object> params) {
for (String key : params.keySet()) {
query.setParameter(key, params.get(key));
}
}
sql语句的拼写
你使用jpa ,难免会遇到自己写sql的情况,所以 自己写一个 生成sql语句的util 很有好处
String querySql = UnexSqlUtil.sql_queryByCondition(entity, params);
eg:
select *
from
po where 1=1
and a=a and b=b
//所以po 是需要动态的, and a=a 也是 动态的 ,于是 1=1 是一个 常量, and 也是
private static final String DEFAULT_CONDITION = " 1=1 ";
private static final String JOINT_AND = " AND ";
public static String sql_queryByCondition(Object entity, Map<String, Object> params) {
StringBuffer sb = new StringBuffer("SELECT * FROM ");
// 根据传入的对象,获取到其 数据库中的名字sb.append(getTableName(entity.getClass())).append(" WHERE " + DEFAULT_CONDITION);
Class<? extends Object> cls = entity.getClass();
while (null != cls) {
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
appendCondition(sb, params, entity, field, JOINT_AND);
}
cls = cls.getSuperclass();
}
return sb.toString();
}
// 根据 对象获取 其在数据库中的名字 ,实体类中 会有注解
eg:@Entity(name = "T_NOTIFY_SCHE")
public class NotifySchePo extends UnexBasePo {}
public static String getTableName(Class<? extends Object> clazz) {
Entity entity = clazz.getAnnotation(Entity.class);
if (entity != null) {
String name = entity.name().toUpperCase();
if (StringUtils.isNoneBlank(name)) {
return name;
}
}
Table table = clazz.getAnnotation(Table.class);
if (table != null) {
String name = table.name().toUpperCase();
if (StringUtils.isNoneBlank(name)) {
return name;
}
}
throw new UnexDalException("Entity define error!");
}
// 为了 形成 and a=a and b=b
而且 tb_user 和TbUser 需要进行转化,于是 我需要将 遇到U时,将其变成 _u ,
private static String getFieldName(String propertyName) {
StringBuffer sb = new StringBuffer();
for (byte b : propertyName.getBytes()) {
if (b >= 'a' && b <= 'z') {
// 小写字母转大写字母
sb.append((char) (b - 32));
} else if (b >= 'A' && b <= 'Z') {
// 大写字母前面加下划线
sb.append('_');
sb.append((char) b);
} else {
// 其他字符保留原样
sb.append((char) b);
}
}
return sb.toString();
}
// 而且 我需要将 对象中的私有属性值 取出来,肯定需要用到 反射,于是 就需要用 getTbUser()
/*
* 把一个字符串的第一个字母大写
*/
private static String getMethodName(String fildeName) {
byte[] items = fildeName.getBytes();
items[0] = (byte) ((char) items[0] - 'a' + 'A');
return new String(items);
}
// 而且在 jpa 的底层sql中, String 和非 String 的传入方式是不一样的
private static void appendCondition(StringBuffer sb, Map<String, Object> params, Object entity, Field field, String joint) {
String propertyName = field.getName();
// 属性之上的 注解中的 列名
Column column = field.getAnnotation(Column.class);
// 表中之 列名
String fieldName = (null == column || StringUtil.isBlank(column.name())) ? getFieldName(propertyName) : column.name();
try {
Method readMethod = entity.getClass().getMethod("get" + getMethodName(propertyName));// 根据 反射中获得这个 方法
Object value = readMethod.invoke(entity);
if (value instanceof String) {
if (!StringUtil.isEmpty((String) (value))) {
sb.append(joint).append(fieldName).append(" = :").append(propertyName);
params.put(propertyName, value);
}
} else {
if (value != null) {
sb.append(joint).append(fieldName).append(" = :").append(propertyName);
params.put(propertyName, value);
}
}
} catch (Exception e) {
throw new UnexDalException("Entity define error!");
}
}
以上就是 jpa 的整合,
具体的使用
@Service
public class PaymentRefundFlowUnionpayServiceImpl extends UnexBaseServiceImpl<PaymentRefundFlowUnionpayPo>
implements IPaymentRefundFlowUnionpayService {
}