MybatisPlus支持SqlServer数据库空间数据类型的增改查

前言

MybatisPlus通过内置的一些方法使我们可以不需要编写sql代码即可执行sql语句,而对于空间类型却不太支持,所以本文章是对MybatisPlus支持空间数据类型的一种优化

注:本文章仅针对SqlServer的空间数据进行优化,因其语句执行比较友好。专业的空间数据库没学过,在此不讨论。虽然也可以支持MySQL,但比较麻烦,所以就没写了

环境

springboot:2.7.10

mybatis-plus:3.5.5

系统:Windows 11

java:1.8.351

Maven:3.9.2

实验

1、准备一张表

CREATE TABLE [geo](
    [id] bigint PRIMARY KEY,
    [location] geography
);

2、编写实体类

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

@Data
public class Geo {
    @TableId
    private Long id;
    @TableField(value = "location.STAsText()")
    private String location;
}

这里直接通过@TableField注解注入调用函数的sql,在使用IService的方法时会自动带上location作为别名,以能正确映射到该属性上

3、Mapper和Service

省略,以平常一致

4、通过拦截器修改sql

第2步只是确保了查询时能够转为wkt,但插入和更新会自动使用@TableField注解里的名字,这将导致错误,接下来,就是要修复该错误了。

import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Properties;

@Component
// Intercepts注解用于声明拦截器,此处将会拦截StatementHandler类的prepare(Coonection,Integer)方法
@Intercepts({
        @Signature(
                type = StatementHandler.class,
                method = "prepare",
                args ={Connection.class, Integer.class}
        )
})
public class GeoInterceptor implements Interceptor {
    @Lazy
    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 获取拦截的对象
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        // 获取该方法所对应的sql命令类型
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        // 如果是插入和更新命令,则进行处理
        if (mappedStatement.getSqlCommandType() == SqlCommandType.INSERT || mappedStatement.getSqlCommandType() == SqlCommandType.UPDATE) {
            // 获取sql
            BoundSql boundSql = statementHandler.getBoundSql();
            String sql = boundSql.getSql();
            // 移除后面的函数
            sql = sql.replaceAll("\\.STAsText\\(\\)", "");
            // 将新的sql放回去
            Field delegate = RoutingStatementHandler.class.getDeclaredField("delegate");
            delegate.setAccessible(true);
            Object o = delegate.get(statementHandler);
            delegate.setAccessible(false);
            Field field = BaseStatementHandler.class.getDeclaredField("boundSql");
            field.setAccessible(true);
            field.set(o, new BoundSql(sqlSessionFactory.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject()));
            field.setAccessible(false);
        }
        // 后续执行
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}

至此,大功告成

结语

该拦截器是Mybatis的功能,所以也会对Mapper里面自己手写sql的方法也会生效,若要避免这种情况,需要进行额外处理。

本功能将SqlServer的空间数据类型转为字符串进行传输(插入更新时SqlServer会对字符串自动进行转换,MySQL则必须使用函数转为空间数据才可进行插入更新),后续通过类型处理器可将其转为几何类来方便计算。

总之呢,个人感觉用处不大,本文章仅为学习时的记录。毕竟要用空间数据类型的话,大多数时候都是需要使用空间函数的,所以,倒不如手写SQL还来的快速方便

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java连接SQL Server数据库可以使用JDBC(Java Database Connectivity)技术。以下是实现的基本步骤: 1. 导入SQL Server JDBC驱动程序 在Java项目中,需要将SQL Server JDBC驱动程序添加到类路径中。可以从Microsoft官网下载最新版本的驱动程序。 2. 建立数据库连接 使用JDBC API中的DriverManager类和Connection接口建立与SQL Server数据库的连接。需要提供数据库的URL、用户名和密码等信息。 3. 执行SQL语句 使用Connection接口的createStatement()方法创建一个Statement对象,然后使用该对象执行SQL语句。可以执行加、删除、修询等操作。 4. 处理结果集 如果执行的是询操作,可以使用ResultSet接口获取询结果集。可以使用ResultSet对象的方法遍历结果集,获取每一行数据的各个字段值。 5. 关闭数据库连接 使用Connection接口的close()方法关闭数据库连接,释放资源。 以上是Java连接SQL Server数据库实现的基本步骤。具体实现可以参考JDBC API文档和SQL Server JDBC驱动程序的使用说明。 ### 回答2: Java连接SQL Server数据库可以使用JDBC(Java Database Connectivity)技术,JDBC是Java程序访问各种关系型数据库的标准API。 首先需要下载并安装SQL Server驱动程序(.jar文件),然后在Java程序中导入驱动程序。 在使用JDBC访问SQL Server数据库时,需要先建立数据库连接。可以使用以下代码建立连接: ``` // 加载JDBC驱动 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); // 建立数据库连接 String url = "jdbc:sqlserver://127.0.0.1:1433;databaseName=mydb"; String user = "sa"; String password = "123456"; Connection conn = DriverManager.getConnection(url, user, password); ``` 其中,url中的127.0.0.1是本地IP地址,1433是SQL Server默认端口号,mydb是数据库名称,user和password是登录用户名和密码。如果没有用户名和密码,可以省略。 连接成功后,就可以使用Java代码进行操作。以下是加一条记录的示例代码: ``` String sql = "insert into student(name,age) values('Tom',20)"; Statement stmt = conn.createStatement(); int count = stmt.executeUpdate(sql); ``` 其中,sql是SQL语句,stmt是Statement对象,通过conn对象的createStatement()方法创建,count是影响的行数。 以下是数据的示例代码: ``` String sql = "select * from student"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); while(rs.next()) { String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println(name + " " + age); } ``` 其中,rs是ResultSet对象,通过stmt对象的executeQuery()方法创建,每次调用rs.next()方法可以将结果集指针移动到下一行。rs.getString("name")和rs.getInt("age")分别表示获取该行记录中name和age字段的值。 删除和修操作也类似,只需要变SQL语句即可。 完成操作后,需要关闭数据库连接,以便释放资源。以下是关闭连接的示例代码: ``` rs.close(); stmt.close(); conn.close(); ``` 以上就是Java连接SQL Server数据库实现的基本方法。实际应用中,可能需要结合Spring等框架来优化代码。 ### 回答3: Java作为一种面向对象的编程语言,具有类库丰富、应用范围广泛和跨平台的特点,被广泛应用于各个领域。在Java应用程序中,访问数据库是一项非常重要的任务。SQL Server是Microsoft公司开发的一种关系型数据库管理系统,在企业应用中被广泛使用。因此,本文将介绍如何使用Java连接SQL Server数据库实现的操作。 步骤一:加载SQL Server驱动 在Java程序中访问SQL Server数据库,首先需要将SQL Server驱动加载到程序中。在Java 1.6之后,可以使用JDBC 4.0自动加载驱动。以下是加载SQL Server驱动的示例代码: Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); 步骤二:建立连接 在加载完驱动后,要建立与数据库的连接。SQL Server数据库使用JDBC URL来标识数据库和访问方式。以下是连接SQL Server数据库的示例代码: String url = "jdbc:sqlserver://localhost:1433;databaseName=mydatabase"; Connection con = DriverManager.getConnection(url, "myuser", "mypassword"); 其中,localhost:1433表示SQL Server数据库的IP地址和端口号;mydatabase表示要连接的数据库名称;myuser和mypassword分别是连接数据库的用户名和密码。 步骤三:执行SQL语句 连接成功后,可以执行SQL语句来实现的操作。Java中的PreparedStatement类可以通过占位符(?)来提高性能和安全性。以下是实现向表中插入数据的示例代码: String sql = "INSERT INTO mytable(name, age) VALUES (?, ?)"; PreparedStatement pstmt = con.prepareStatement(sql); pstmt.setString(1, "Tom"); pstmt.setInt(2, 26); pstmt.executeUpdate(); 其中,?号用于占位符,pstmt.setString(1, "Tom")和pstmt.setInt(2, 26)分别用于设置占位符的值。 如果要实现删除、更新和询操作,可以通过以下示例代码实现: // 删除数据 String sql = "DELETE FROM mytable WHERE id = ?"; PreparedStatement pstmt = con.prepareStatement(sql); pstmt.setInt(1, 1); pstmt.executeUpdate(); // 更新数据 String sql = "UPDATE mytable SET age = ? WHERE id = ?"; PreparedStatement pstmt = con.prepareStatement(sql); pstmt.setInt(1, 28); pstmt.setInt(2, 1); pstmt.executeUpdate(); // 数据 String sql = "SELECT * FROM mytable WHERE name = ?"; PreparedStatement pstmt = con.prepareStatement(sql); pstmt.setString(1, "Tom"); ResultSet rs = pstmt.executeQuery(); while(rs.next()){ int id = rs.getInt("id"); String name = rs.getString("name"); int age = rs.getInt("age"); } 其中,rs.next()方法用于指向下一行,getId("id")、getString("name")和getInt("age")分别用于获取指定列的值。 步骤四:关闭连接 数据库连接是一种资源,需要在使用完毕后关闭以释放资源。以下是关闭连接的示例代码: if (rs != null) rs.close(); if (pstmt != null) pstmt.close(); if (con != null) con.close(); 以上是Java连接SQL Server数据库实现的方法和步骤。在实际开发中,可以根据具体的需求和业务逻辑来灵活使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值