介绍:点击打开链接
(1)为什么要引入JPA
JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
(2)如果使用传统mybatis,要对数据库做操作需要在映射文件中写SQL语句
有pojo持久类,如何去实现一个对数据库表的映射呢?加注解
(3)数据库主键的情况
1) 一个值主键,自增
2) 符合主键(联合),多个字段
3) 没主键(把所有的字段值一起作为主键)表设计,哪怕真的业务上不需要主键,这种方式会导致查询变慢,所有表必须有主键
(4)通用Mapper+JPA(可以应用到任何项目中从而减少项目的代码编写)
解决问题:实现表和数据库的映射,自动生成SQL语句。
表的映射:在pojo持久化对象上通过JPA提供注解来实现
表
@Table实现类和表直接的映射,类可以获得,通过反射,获取类的名称,就可以获取类上的注解,从而找到注解中的name属性获取其值,其值就是配置的表名
字段
可以获取类,通过反射,可以获取类的所有属性,获取每个属性的名称,也可以获取这个属性上面的注解@Colum,就可以获取到name属性。如果有Column,数据库字段就是配置的值,如果没有Column就那属性名作为字段名称。
字段类型=属性类型
可以通过上面的反射过程可以写单表SQL语句了吗?
通用Mapper采用Mybatis提供专门注解,@InsertProvider
select
insert(insert into tb_item_cat (id,name) value(?,?) ) 参数值就从pojo中获取
update
delete
where(如果字段为null就不拼,如果不为null,就拼)
如果pojo所有的字段都为null,这时就不拼接where条件
如果只有这一个条件:ItemCat.pojo itemCat.name=“电器”
拼接 wherename=”电器”
如下是JPA注解使用:
要使用注解先导入jar包:
<!-- 通用Mapper,封装了单表CRUD操作,极大减少开发者工作量 -->
<dependency>
<groupId>com.github.abel533</groupId>
<artifactId>mapper</artifactId>
<version>2.3.2</version>
</dependency>
package com.liming.manage.pojo;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/*
* 为了通用Mapper加上JPA,描述java持久类和数据库表映射关系
* JPA映射:4个注解就够了
* 1)类和表的映射
* 2)属性和数据库表的字段映射
* 3)标识表的主键
* 4)标识主键自增
*
* select parent_id,name from tb_item_cat
*/
@Table(name="tb_item_cat") //映射数据库表,表名tb_item_cat
public class ItemCat extends BasePojo{
@Id //主键
@GeneratedValue(strategy=GenerationType.IDENTITY) //自增
private Long id;
@Column(name="parent_id") //parentId就是类属性,@Column就是表的字段
private Long parentId;
private String name;
private Integer status;
@Column(name="sort_order")
private Integer sortOrder;
@Column(name="is_parent")
private Boolean isParent;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getSortOrder() {
return sortOrder;
}
public void setSortOrder(Integer sortOrder) {
this.sortOrder = sortOrder;
}
public Boolean getIsParent() {
return isParent;
}
public void setIsParent(Boolean isParent) {
this.isParent = isParent;
}
}
通用mapper坐标(导入相应的jar包)
<!-- 通用Mapper,封装了单表CRUD操作,极大减少开发者工作量 -->
<dependency>
<groupId>com.github.abel533</groupId>
<artifactId>mapper</artifactId>
<version>2.3.2</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
通用mapper接口
package com.jt.common.mapper;
import java.util.List;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
public interface SysMapper<T> {
/**
* 根据主键ID批量删除
*
* @param key
* @return
*/
@DeleteProvider(type = SysMapperProvider.class, method = "dynamicSQL")
int deleteByIDS(@Param("ids") Object[] key);
/**
* 根据实体类不为null的字段进行查询,条件全部使用=号and条件
*
* @param record
* @return
*/
@SelectProvider(type = SysMapperProvider.class, method = "dynamicSQL")
List<T> select(T record);
/**
* 根据实体类不为null的字段查询总数,条件全部使用=号and条件
*
* @param record
* @return
*/
@SelectProvider(type = SysMapperProvider.class, method = "dynamicSQL")
int selectCount(T record);
/**
* 根据主键进行查询,必须保证结果唯一 单个字段做主键时,可以直接写主键的值 联合主键时,key可以是实体类,也可以是Map
*
* @param key
* @return
*/
@SelectProvider(type = SysMapperProvider.class, method = "dynamicSQL")
T selectByPrimaryKey(Object key);
/**
* 插入一条数据 支持Oracle序列,UUID,类似Mysql的INDENTITY自动增长(自动回写) 优先使用传入的参数值,参数值空时,才会使用序列、UUID,自动增长
*
* @param record
* @return
*/
@InsertProvider(type = SysMapperProvider.class, method = "dynamicSQL")
int insert(T record);
/**
* 插入一条数据,只插入不为null的字段,不会影响有默认值的字段 支持Oracle序列,UUID,类似Mysql的INDENTITY自动增长(自动回写)
* 优先使用传入的参数值,参数值空时,才会使用序列、UUID,自动增长
*
* @param record
* @return
*/
@InsertProvider(type = SysMapperProvider.class, method = "dynamicSQL")
int insertSelective(T record);
/**
* 根据实体类中字段不为null的条件进行删除,条件全部使用=号and条件
*
* @param key
* @return
*/
@DeleteProvider(type = SysMapperProvider.class, method = "dynamicSQL")
int delete(T key);
/**
* 通过主键进行删除,这里最多只会删除一条数据 单个字段做主键时,可以直接写主键的值 联合主键时,key可以是实体类,也可以是Map
*
* @param key
* @return
*/
@DeleteProvider(type = SysMapperProvider.class, method = "dynamicSQL")
int deleteByPrimaryKey(Object key);
/**
* 根据主键进行更新,这里最多只会更新一条数据 参数为实体类
*
* @param record
* @return
*/
@UpdateProvider(type = SysMapperProvider.class, method = "dynamicSQL")
int updateByPrimaryKey(T record);
/**
* 根据主键进行更新 只会更新不是null的数据
*
* @param record
* @return
*/
@UpdateProvider(type = SysMapperProvider.class, method = "dynamicSQL")
int updateByPrimaryKeySelective(T record);
}
通用mapper扩展,可以批量删除
package com.jt.common.mapper;
import static org.apache.ibatis.jdbc.SqlBuilder.BEGIN;
import static org.apache.ibatis.jdbc.SqlBuilder.DELETE_FROM;
import static org.apache.ibatis.jdbc.SqlBuilder.SQL;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.scripting.xmltags.MixedSqlNode;
import org.apache.ibatis.scripting.xmltags.SqlNode;
import org.apache.ibatis.scripting.xmltags.StaticTextSqlNode;
import com.github.abel533.mapper.MapperProvider;
import com.github.abel533.mapperhelper.EntityHelper;
import com.github.abel533.mapperhelper.MapperHelper;
public class SysMapperProvider extends MapperProvider {
public SysMapperProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
public SqlNode deleteByIDS(MappedStatement ms) {
Class<?> entityClass = getSelectReturnType(ms);
Set<EntityHelper.EntityColumn> entityColumns = EntityHelper.getPKColumns(entityClass);
EntityHelper.EntityColumn column = null;
for (EntityHelper.EntityColumn entityColumn : entityColumns) {
column = entityColumn;
break;
}
List<SqlNode> sqlNodes = new ArrayList<SqlNode>();
// 开始拼sql
BEGIN();
// delete from table
DELETE_FROM(tableName(entityClass));
// 得到sql
String sql = SQL();
// 静态SQL部分
sqlNodes.add(new StaticTextSqlNode(sql + " WHERE " + column.getColumn() + " IN "));
// 构造foreach sql
SqlNode foreach = new ForEachSqlNode(ms.getConfiguration(), new StaticTextSqlNode("#{"
+ column.getProperty() + "}"), "ids", "index", column.getProperty(), "(", ")", ",");
sqlNodes.add(foreach);
return new MixedSqlNode(sqlNodes);
}
}