java注解动态sql,springboot根据表名和字段查询和更新实现动态sql(jpa,mybatis)

最近需要做一个根据表名和字段更新表的功能,项目结构是springboot+jpa,记录如下:

1.经查阅资料jpa和hibernate自带对原生sql的支持都是不支持该操作的,原因是:jpa和hibernate在进行参数替换的时候是使用占位符的形式,防止了sql的注入,在解析会给参数带上单引号,但是可以通过定义原生的sql进行解决动态sql查询,但无法实现动态sql更新,如果需要更新必须获取到表对应的实体类

例子实现动态查询sql,假设目前有两张表,表ta、tb,拥有相同的字段 id 、name、desc

pom.xml

org.springframework.boot

spring-boot-starter-data-jpa

mysql

mysql-connector-java

runtime

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-starter-web

ta实体类

package com.example.demo;

import javax.persistence.Basic;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.Id;

import java.util.Objects;

/**

* Author: hezishan

* Date: 2018/7/11.

* Description:

**/

@Entity

public class Ta {

private int id;

private String name;

private String desc;

@Id

@Column(name = "id")

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

@Basic

@Column(name = "name")

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Basic

@Column(name = "desc")

public String getDesc() {

return desc;

}

public void setDesc(String desc) {

this.desc = desc;

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

Ta ta = (Ta) o;

return id == ta.id &&

Objects.equals(name, ta.name) &&

Objects.equals(desc, ta.desc);

}

@Override

public int hashCode() {

return Objects.hash(id, name, desc);

}

}

动态sql类:

entityManager来定义原生sql

package com.example.demo;

import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

import java.util.Map;

/**

* Author: hezishan

* Date: 2018/7/11.

* Description:

**/

@Component

public class UpdateResponsity {

@PersistenceContext //注入的是实体管理器,执行持久化操作

EntityManager entityManager;

public Object selectByTableNameAndAttr(String tableName,String attr,String attrVal){

String sql="select * from "+tableName + " where "+attr+" = "+attrVal;

Object object=entityManager.createNativeQuery(sql).getSingleResult();

return object;

}

}

测试类:

@RunWith(SpringRunner.class)

@SpringBootTest

public class DemoApplicationTests {

@Autowired

UpdateResponsity updateResponsity;

@Autowired

@Test

public void contextLoads() {

Object object= updateResponsity.selectByTableNameAndAttr("ta","id","1");

Object object1= updateResponsity.selectByTableNameAndAttr("tb","id","1");

System.out.println(object);

System.out.println(object1);

}

}

2.jpa和hibernate做不了,可mybatis可以实现,mybatis不同于其他持久层框架就是其能实现动态sql,mybatis提供两种方式参数的传入,分别是#、$.其区别如下:mybatis 在对 sql 语句进行预编译之前,会对 sql 进行动态解析,解析为一个 BoundSql 对象,也是在此处对动态 SQL 进行处理的。

在动态 SQL 解析阶段, #{ } 和 ${ } 会有不同的表现:#{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符。例如,sqlMap 中如下的 sql 语句

select * from user where name = #{name};

解析为:

select * from user where name = ?;

一个 #{ } 被解析为一个参数占位符 ? 。

而${ } 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换

例如,sqlMap 中如下的 sql

select * from user where name = '${name}';

当我们传递的参数为 "ruhua" 时,上述 sql 的解析为:

select * from user where name = "ruhua";

预编译之前的 SQL 语句已经不包含变量 name 了。

综上所得, ${ } 的变量的替换阶段是在动态 SQL 解析阶段,而 #{ }的变量的替换是在 DBMS 中。

1.1使用注解方式:

pom.xml

dependency>

org.springframework.boot

spring-boot-starter

org.springframework.boot

spring-boot-starter-web

org.mybatis.spring.boot

mybatis-spring-boot-starter

1.3.2

mysql

mysql-connector-java

org.springframework.boot

spring-boot-starter-test

test

UpdateResposity.java:在表名和属性名的使用$作为值传入

/**

* Author: hezishan

* Date: 2018/7/11.

* Description:

**/

@Mapper

public interface UpdateResposity {

@Select("select ${id} as id,${val} as val from ${tableName} where ${atrr}=#{attrVal} ")

public MapqueryByTableNameAndAtrr(@Param("tableName") String tableName,@Param("id") String id,@Param("val") String val,@Param("atrr") String atrr,@Param("attrVal") String attrVal);

@Update("update ${tableName} set ${updateAttr}=#{updateAttrVal} where ${condition}=#{conditionVal}")

public void updateByTableNameAndAttr(@Param("tableName") String tableName,@Param("condition") String condition,@Param("conditionVal") String conditionVal,@Param("updateAttr") String updateAttr,@Param("updateAttrVal") String updateAttrVal);

}

测试:

@RunWith(SpringRunner.class)

@MapperScan("com.example.demo")

@SpringBootTest

public class DemoApplicationTests {

@Autowired

UpdateResposity resposity;

@Test

public void contextLoads() {

Mapob =resposity.queryByTableNameAndAtrr("ta","id","name","id","1");

if(ob!=null){

String name=ob.get("val")+"hello ";

System.out.println(ob.get("id"));

resposity.updateByTableNameAndAttr("ta","id",ob.get("id")+""

,"name",name);

}

System.out.println(ob);

}

}

1.2使用xml配置文件方式:

pom.xml

org.mybatis.spring.boot

mybatis-spring-boot-starter

1.3.2

tk.mybatis

mapper-spring-boot-starter

1.1.7

mysql

mysql-connector-java

runtime

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

mapper接口:

/**

* Author: hezishan

* Date: 2018/7/12.

* Description:

**/

public interface TMapper {

MapselectByTableNameAndPrimaryAttr(@Param("tableName") String tableName,@Param("conditions")Listconditions);

List> selectByTableNameAndCommonAttr(@Param("tableName") String tableName,@Param("conditions")Listconditions);

void updateByTableName(@Param("tableName") String tableName,@Param("changeList")ListchangeList,@Param("conditions")Listconditions);

}mapper.xml

select * from ${tableName}

${condition.attr}=${condition.value}

select * from ${tableName}

${condition.attr}=${condition.value}

update ${tableName} set

${change.attr}= #{change.value}

${condition.attr}=${condition.value}

condition类:存放属性、属性值

/**

* Author: hezishan

* Date: 2018/7/12.

* Description:

**/

public class Condition {

private String attr;

private String opera;

private Object value; //get set}

测试:

public String update() {

Listlist=new ArrayList();

Condition condition=new Condition();

condition.setAttr("id");

condition.setValue(1);

list.add(condition);

Mapmap=tMapper.selectByTableNameAndPrimaryAttr("ta",list);

if(map!=null){

ListchangeList=new ArrayList();

Condition cond=new Condition();

cond.setAttr("name");

cond.setValue("hello world");

changeList.add(cond);

tMapper.updateByTableName("ta",changeList,list);

}

return "success" ;

}

通过上面的简单例子可以看出,使用xml配置方式能够指定多参数,适用范围为大。

提供mybatis带通用mapper逆向工程:https://github.com/hzsbrave/mybatisgenerator.git

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值