Todos os produtos
Search
Central de documentação

Lindorm:Desenvolva aplicações com o framework ORM Java MyBatis

Última atualização: Jun 28, 2026

O LindormTable é compatível com o protocolo MySQL, o que permite usar o framework de Mapeamento Objeto-Relacional (ORM) MyBatis para criar aplicações Java. O MyBatis separa o SQL do código da aplicação ao permitir a definição da lógica de acesso a dados em interfaces de mapper, mantendo a lógica de negócios livre de SQL embutido.

Ao concluir este tutorial, você terá:

  • Adicionado as dependências do MyBatis e do driver JDBC do MySQL a um projeto Maven

  • Configurado o arquivo mybatis-config.xml para conexão com o LindormTable

  • Definido uma interface de mapper com operações de criação, leitura, upsert e exclusão

  • Executado uma demonstração funcional no LindormTable

Pré-requisitos

Antes de começar, verifique se você possui:

Configure o projeto

Etapa 1: Adicione as dependências

No seu projeto Maven, adicione as seguintes dependências ao bloco dependencies no arquivo pom.xml:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.14</version>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.3.0</version>
</dependency>

Etapa 2: Configure a conexão

Na pasta resources, crie o arquivo mybatis-config.xml com as configurações de conexão para o LindormTable:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://<MySQL-compatible endpoint>:33060/<database>?sslMode=disabled&amp;allowPublicKeyRetrieval=true&amp;useServerPrepStmts=true&amp;useLocalSessionState=true&amp;rewriteBatchedStatements=true&amp;cachePrepStmts=true&amp;prepStmtCacheSize=100&amp;prepStmtCacheSqlLimit=50000000"/>
                <property name="username" value="<username>"/>
                <property name="password" value="<password>"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="org.example.UserMapper"/>
    </mappers>
</configuration>

Substitua os seguintes espaços reservados:

Espaço reservado

Descrição

<MySQL-compatible endpoint>

Endpoint compatível com MySQL da sua instância. Para obter esse valor, consulte Visualizar endpoints.

<database>

Nome do banco de dados para conexão. Se omitido, o cliente se conecta ao banco de dados padrão.

<username>

Nome de usuário do banco de dados.

<password>

Senha do banco de dados. Para redefini-la, consulte Alterar senha de usuário.

Escolha do endpoint adequado

Tipo de acesso

Endpoint a ser usado

A partir de uma instância do Elastic Compute Service (ECS) na mesma Virtual Private Cloud (VPC)

Endereço VPC do endpoint compatível com MySQL

Via internet

Endereço público do endpoint compatível com MySQL

Se sua aplicação for executada em uma instância ECS, use o endpoint VPC para garantir maior segurança e menor latência. Para conectar via internet, ative primeiro o endpoint público: no console, acesse Database Connection > Wide Table Engine e clique em Enable Public Endpoint.

Para obter detalhes sobre os parâmetros da string de conexão e como eles melhoram o desempenho, consulte Configuração de conexão.

Etapa 3: Defina o modelo de dados

Crie uma classe User para representar as linhas da tabela de demonstração:

package org.example;

import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.sql.Timestamp;

public class User {
  private int userId;
  private String userName;
  private double height;
  private long score;
  private Timestamp createTime;
  private Date birthday;
  private byte[] digest;

  public User(int userId, String userName, double height, long score,
      Timestamp createTime, Date birthday, byte[] digest) {
    this.userId = userId;
    this.userName = userName;
    this.height = height;
    this.score = score;
    this.createTime = createTime;
    this.birthday = birthday;
    this.digest = digest;
  }

  public int getUserId() { return userId; }
  public void setUserId(int userId) { this.userId = userId; }

  public String getUserName() { return userName; }
  public void setUserName(String userName) { this.userName = userName; }

  public double getHeight() { return height; }
  public void setHeight(double height) { this.height = height; }

  public long getScore() { return score; }
  public void setScore(long score) { this.score = score; }

  public Timestamp getCreateTime() { return createTime; }
  public void setCreateTime(Timestamp createTime) { this.createTime = createTime; }

  public Date getBirthday() { return birthday; }
  public void setBirthday(Date birthday) { this.birthday = birthday; }

  public byte[] getDigest() { return digest; }
  public void setDigest(byte[] digest) { this.digest = digest; }

  @Override
  public String toString() {
    return "User{" + "userId=" + userId + ", userName='" + userName + '\'' +
        ", height=" + height + ", score=" + score + ", createTime=" + createTime +
        ", birthday=" + birthday + ", digest=" + new String(digest, StandardCharsets.UTF_8) + '}';
  }
}

Etapa 4: Crie o mapper

Crie uma interface UserMapper. Cada método tem uma anotação com a instrução SQL correspondente executada no LindormTable:

package org.example;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

public interface UserMapper {

  @Update("create table if not exists demo_user(`id` INT, `name` VARCHAR, `height` DOUBLE, `score` BIGINT, `createtime` TIMESTAMP, `birthday` DATE, digest VARBINARY, primary key(id))")
  void createUserTable();

  @Update("drop table if exists demo_user")
  void dropUserTable();

  @Insert("upsert into demo_user(`id`,`name`,`height`,`score`,`createtime`,`birthday`,`digest`) values(#{userId},#{userName},#{height},#{score},#{createTime},#{birthday},#{digest})")
  int upsertUser(User user);

  @Delete("delete from demo_user where `id` = #{userId}")
  int deleteUser(@Param("userId") int userId);

  @Select("select * from demo_user where `id` = #{userId}")
  User selectOneUser(@Param("userId") int userId);

  @Select("select * from demo_user")
  List<User> selectAllUser();
}

Todas as operações de escrita usam upsert em vez de insert — esta é a sintaxe preferencial do LindormTable para inserir ou atualizar linhas em uma única instrução.

Etapa 5: Escreva o código da aplicação

Carregue a configuração, abra uma SqlSession e execute operações CRUD por meio do mapper:

package org.example;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.sql.Timestamp;

public class MybatisDemo {
  public static void main(String[] args) throws Exception {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    try (SqlSession session = sqlSessionFactory.openSession()) {
      UserMapper mapper = session.getMapper(UserMapper.class);

      // Create the table
      mapper.createUserTable();

      // Verify the table is empty
      System.out.println(mapper.selectAllUser());

      // Insert two users
      User user1 = new User(1, "zhangsan", 1.8, 100,
          new Timestamp(System.currentTimeMillis()),
          Date.valueOf("1995-03-02"),
          "hello".getBytes(StandardCharsets.UTF_8));
      User user2 = new User(2, "lisi", 1.7, 90,
          new Timestamp(System.currentTimeMillis()),
          Date.valueOf("1996-08-02"),
          "world".getBytes(StandardCharsets.UTF_8));

      mapper.upsertUser(user1);
      mapper.upsertUser(user2);

      // Query all users and a single user
      System.out.println(mapper.selectAllUser());
      System.out.println(mapper.selectOneUser(1));

      // Delete user1 and verify
      mapper.deleteUser(1);
      System.out.println(mapper.selectAllUser());

      // Update user2's score using upsert and verify
      user2.setScore(99);
      mapper.upsertUser(user2);
      System.out.println(mapper.selectAllUser());

      // Clean up
      mapper.dropUserTable();
    }
  }
}

Exemplo completo

Baixe o projeto de exemplo completo: mybatis-demo.zip.

Após uma execução bem-sucedida, a saída será semelhante a esta:

[User{userId=1, userName='zhangsan', height=1.8, score=100, createTime=2023-12-02 09:39:17.63, birthday=1995-03-02, digest=hello}, User{userId=2, userName='lisi', height=1.7, score=90, createTime=2023-12-02 09:39:17.63, birthday=1996-08-02, digest=world}]
User{userId=1, userName='zhangsan', height=1.8, score=100, createTime=2023-12-02 09:39:17.63, birthday=1995-03-02, digest=hello}
[User{userId=2, userName='lisi', height=1.7, score=90, createTime=2023-12-02 09:39:17.63, birthday=1996-08-02, digest=world}]
[User{userId=2, userName='lisi', height=1.7, score=99, createTime=2023-12-02 09:39:17.63, birthday=1996-08-02, digest=world}]

Perguntas frequentes

Por que o método selectAllUser() lança a exceção "ExecutionPlaceholder cannot be cast to java.util.List"?

O erro completo é:

### Cause: java.lang.ClassCastException: class org.apache.ibatis.executor.ExecutionPlaceholder cannot be cast to class java.util.List

Os objetos SqlSession e Mapper no MyBatis não são seguros para threads. Esse erro ocorre quando múltiplas threads acessam simultaneamente a mesma SqlSession ou o mesmo Mapper. Certifique-se de que cada thread crie sua própria SqlSession e obtenha seu próprio mapper a partir dela.

Qual a diferença entre os espaços reservados #{} e ${}?

**#{}**

**${}**

Implementação

Vinculação de parâmetros pré-compilados via JDBC PreparedStatement

Substituição direta de string

Risco de injeção de SQL

Nenhum

Sim

Desempenho

Alto — o plano de execução é reutilizável

Baixo — cada instrução é analisada novamente

Quando usar

Para vincular valores dinâmicos, como condições WHERE

Para injetar fragmentos SQL, como nomes de tabelas ou colunas ORDER BY

Use #{} para todos os valores de parâmetros. Reserve ${} apenas para estruturas SQL dinâmicas em que a vinculação parametrizada não for possível.

Importante

O espaço reservado #{} só gera uma consulta verdadeiramente parametrizada quando useServerPrepStmts=true está definido na string de conexão. Sem essa configuração, o driver JDBC do MySQL reescreve a instrução como um literal de string em tempo de execução, ignorando a pré-compilação. Para mais detalhes, consulte Configuração de conexão.

Próximos passos