通用mapper的学习与使用

通用mapper的学习与使用

本文是基于SpringBoot 2.0.4.release环境,学习和使用通用mapper:


一、通用mapper的注解使用

(1)@Table

  • 建立实体类与数据库表之间的映射关系
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "table_emp")
public class Employee {
    private Integer empId;
    private String empName;
    private Double empSalary;
    private Integer empAge;
}

(2)@Column

  • 建立实体类字段与数据库表字段之间的映射关系
  • 实体类字段使用驼峰式命名
  • 数据库表字段使用_下划线分割
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "table_emp")
public class Employee {
    private Integer empId;
    @Column(name = "emp_name_value")
    private String empName;
    private Double empSalary;
    private Integer empAge;
}

(3)@Id

  • 标记数据库表中的主键
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "table_emp")
public class Employee {
	@Id
    private Integer empId;
    @Column(name = "emp_name_value")
    private String empName;
    private Double empSalary;
    private Integer empAge;
}

(4)@GeneratedValue

  • 让通用mapper执行insert操作之后将数据库自动生成的主键值回写到实体类对象中
  • 基于自增主键用法:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "table_emp")
public class Employee {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer empId;
    @Column(name = "emp_name_value")
    private String empName;
    private Double empSalary;
    private Integer empAge;
}
  • 基于序列主键用法:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "table_emp")
public class Employee {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY, generator="select SEQ_ID.nextval from dual")
    private Integer empId;
    @Column(name = "emp_name_value")
    private String empName;
    private Double empSalary;
    private Integer empAge;
}

(5)@Transient

  • 标记实体类中的额外的属性,用来告诉通用mapper这不是表中的字段
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "table_emp")
public class Employee {
	@Id
    private Integer empId;
    @Column(name = "emp_name_value")
    private String empName;
    private Double empSalary;
    private Integer empAge;
    @Transient
    private Date updated;
}

二、通用mapper的常用方法

(0)接口继承关系

  • Mapper的继承关系
public interface Mapper<T> extends 
	BaseMapper<T>, 
	ExampleMapper<T>, 
	RowBoundsMapper<T>, 
	Marker
  • BaseMapper的继承关系
public interface BaseMapper<T> extends 
	BaseSelectMapper<T>, 
	BaseInsertMapper<T>, 
	BaseUpdateMapper<T>, 
	BaseDeleteMapper<T> 
  • BaseSelectMapper的继承关系
public interface BaseSelectMapper<T> extends 
	SelectOneMapper<T>,
	SelectMapper<T>, 
	SelectAllMapper<T>, 
	SelectCountMapper<T>, 
	SelectByPrimaryKeyMapper<T>, 
	ExistsWithPrimaryKeyMapper<T> 
  • BaseInsertMapper的继承关系
public interface BaseInsertMapper<T> extends 
	InsertMapper<T>, 
	InsertSelectiveMapper<T> 
  • BaseUpdateMapper的继承关系
public interface BaseUpdateMapper<T> extends
	UpdateByPrimaryKeyMapper<T>,
	UpdateByPrimaryKeySelectiveMapper<T> 
  • BaseDeleteMapper的继承关系
public interface BaseDeleteMapper<T> extends 
	DeleteMapper<T>, 
	DeleteByPrimaryKeyMapper<T>
  • ExampleMapper的继承关系
public interface ExampleMapper<T> extends 
	SelectByExampleMapper<T>, 
	SelectOneByExampleMapper<T>, 
	SelectCountByExampleMapper<T>, 
	DeleteByExampleMapper<T>, 
	UpdateByExampleMapper<T>, 
	UpdateByExampleSelectiveMapper<T> 

三、通用BaseSelectMapper的常用方法

(1)selectOne(T record)

  • 只能返回一条记录
  • 使用非空的值生成where子句
  • 在条件表达式中使用=进行比较
public Employee getOne(){
		Employee employeeQueryCondition = new Employee(null, "bob", 5560.11, null);
        return empMapper.selectOne(employeeQueryCondition);
    }

(2)selectAll()

  • 返回所有记录
public List<Employee> getAll(){
	
        return empMapper.selectAll();
    }

(3)selectCount(T record)

  • 返回记录的个数
public Integer getCount(){
		Employee employeeQueryCondition = new Employee(null, "bob", 5560.11, null);
        return empMapper.selectCount(employeeQueryCondition);
    }

(4)selectByPrimaryKey(T id)

public Employee getById(T id){
	
        return empMapper.selectByPrimaryKey(id);
    }

(5)isExists(T id)

public Boolean isExists(Integer id){

        return empMapper.existsWithPrimaryKey(id);
    }

四、通用BaseInsertMapper的常用方法

(1)insert(T record)

public Integer insert(){
		Employee employee= new Employee(null, "bob", 5560.11, null);
        return empMapper.insert(employee);
    }

(2)insertSelective(T record)

  • 效率比insert方法高,为null的字段不会出现在SQL语句中
public Integer insert(){
		Employee employee= new Employee(null, "bob", 5560.11, null);
        return empMapper.insertSelective(employee);
    }

五、通用BaseUpdateMapper的常用方法

(1)updateByPrimaryKey(T record)

public Integer updateByPrimaryKey(){
		Employee employee= new Employee(1, "bob", 5560.11, 23);
        return empMapper.updateByPrimaryKey(employee);
    }

(2)updateByPrimaryKeySelective(T record)

  • 为null的字段不会出现在SQL语句中
public Integer updateByPrimaryKeySelective(){
		Employee employee= new Employee(1, "bob", 5560.11, null);
        return empMapper.updateByPrimaryKeySelective(employee);
    }

六、通用BaseDeleteMapper的常用方法

(1)delete(T record)

  • 尽量不要用,会删除多个数据记录
public Integer delete(){
		Employee employee= new Employee(1, "bob", 5560.11, 23);
        return empMapper.delete(employee);
    }

(2)deleteByPrimaryKey(T id)

  • 为null的字段不会出现在SQL语句中
public Integer deleteByPrimaryKey(){
		Integer empId = 5;
        return empMapper.deleteByPrimaryKey(empId);
    }

七、通用ExampleMapper的常用方法

(1)selectByExample(Example example)

@Test
    public void testSelectByExample(){
        // 目标:where (emp_salary > 3000 and emp_age < 25) or (emp_salary < 5000 and emp_age > 30)
        Example example = new Example(Employee.class);

        // 设置排序信息
        example.orderBy("empSalary").asc().orderBy("empAge").desc();
        // 设置去重
        example.setDistinct(true);
        // 设置select字段
        example.selectProperties("empName", "empSalary");

        Criteria criteria01 = example.createCriteria();
        Criteria criteria02 = example.createCriteria();

        criteria01.andGreaterThan("empSalary",3000).andLessThan("empAge",25);
        criteria02.andLessThan("empSalary",5000).andGreaterThan("empAge",30);

        example.or(criteria02);

        List<Employee> employeeList = empMapper.selectByExample(example);
        employeeList.forEach(employee -> {
            System.out.println(employee);
        });
    }

八、自定义mapper接口

根据开发的实际需要对Mapper接口进行定制

  • 自定义通用mapper接口,可以继承任意组合的mapper
  • 放在与mapper不同的包下,否则会出错
public interface MyMapper<T> extends
        SelectAllMapper<T>,
        SelectByExampleMapper<T> {
}
public interface EmpMapper extends MyMapper<Employee> {
}
@Test
public void testSelectAll() {
	List<Employee> list = empMapper.selectAll();
	list.forEach(employee -> {
		System.out.println(employee);
	});
}

九、开启二级缓存

  • 添加CacheNamespace注解
@CacheNamespace
public interface EmpMapper extends MyMapper<Employee> {
}
  • 缺点:
    分布式环境下必然会出现脏数据;
    多表联合查询的情况下极大可能会出现脏数据;

十、复杂类型数据处理

  • 复杂类型User
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name="table_user")
public class User {
    @Id
    private Integer userId;
    private String userName;
    @ColumnType(typeHandler = AddressTypeHandler.class)
    private Address address;
    @ColumnType(typeHandler = SeasonTypeHandler.class)
    private SeasonEnum season;
}
  • AddressTypeHandler
public class AddressTypeHandler extends BaseTypeHandler<Address> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Address address, JdbcType jdbcType) throws SQLException {
        if (address == null)
            return;
        String provice = address.getProvince();
        String city = address.getCity();
        String street = address.getStreet();
        StringBuilder builder = new StringBuilder();

        builder.append(provice).append(",").append(city).append(",").append(street);

        String addressValue = builder.toString();
        ps.setString(i, addressValue);
    }

    @Override
    public Address getNullableResult(ResultSet rs, String columnName) throws SQLException {

        return stringToAddress(rs.getString(columnName));
    }

    @Override
    public Address getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

        return stringToAddress(rs.getString(columnIndex));
    }

    @Override
    public Address getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {

        return stringToAddress(cs.getString(columnIndex));
    }

    private Address stringToAddress(String columnValue){
        if(StringUtils.isBlank(columnValue) || !columnValue.contains(","))
            return null;
        String[] strings = columnValue.split(",");
        String province = strings[0];
        String city = strings[1];
        String street = strings[2];
        return new Address(province,city,street);
    }
}
  • SeasonTypeHandler
public class SeasonTypeHandler extends BaseTypeHandler<SeasonEnum> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, SeasonEnum season, JdbcType jdbcType) throws SQLException {
        if (season == null)
            return;
        String s = season.getSeason();
        ps.setString(i, s);
    }

    @Override
    public SeasonEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {

        return stringToSeason(rs.getString(columnName));
    }

    @Override
    public SeasonEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

        return stringToSeason(rs.getString(columnIndex));
    }

    @Override
    public SeasonEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {

        return stringToSeason(cs.getString(columnIndex));
    }

    private SeasonEnum stringToSeason(String columnValue){
        if(StringUtils.isBlank(columnValue))
            return null;
        return SeasonEnum.valueOf(columnValue);
    }
}

原创文章 98 获赞 143 访问量 167万+

猜你喜欢

转载自blog.csdn.net/qq_32599479/article/details/105938843
今日推荐