什么样的 PG ORM 框架,既能自动映射还能完全控制?

开发 架构
应用开发者在使用高级语言开发时,经常会用到 ORM 框架,它可以减少很多和数据库进行交互方面的工作。

介绍

虽然 ORM 通常将 Java 对象映射到数据库表(反之亦然),但 MyBatis 采取了不同的方法,将 Java 方法映射到 SQL 语句。这使您可以完全控制 SQL 的编写及其后续执行。在映射器的帮助下,MyBatis 也允许自动将数据库对象映射到 Java 对象。

像所有其他的 Java 持久化框架一样,MyBatis 的主要目标是减少使用原始 JDBC 与数据库通信的人力时间和编码要求。它遵循 Apache License 2.0 协议,可以免费使用。

为什么使用 MyBatis?

MyBatis 的设计采用了以数据库为中心的方法,因此如果你的应用程序是由关系型设计驱动的,MyBatis 是一个非常好的选择。如果您正在开发新应用程序,或在现有数据库基础设施之上扩展现有应用程序,这也是一个不错的选择。

MyBatis 可以非常快速、整齐地执行读取操作,因此对于面向分析和报告的应用程序来说,它非常方便。因为它被设计为直接使用 SQL,所以,它让你对数据库执行的查询有低级别和完全的控制权。最重要的是,在 MyBatis 数据映射器的帮助下,Java 中的对象模型和数据库中的数据模型是可以不同的。这为 Java 编码提供了更大的灵活性。

亮点特性

让我们继续使用 'largecities' 表,来演示 MyBatis 的特性。

前提条件

要开始使用 MyBatis,首先你需要下载它的 jar 文件,你可以从项目发布页面获取。该文件需要与 PostgreSQL JDBC 驱动程序一起,处在项目的 classpath 中。

接下来,您需要创建 Java 对象类,如下所示:

package org.rockdata.javabook.mybatis;

public class LargeCities {
    private int rank;
    private String name;

    public int getRank() {
        return rank;
    }
    public void setRank(int rank) {
        this.rank = rank;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

最后,MyBatis 需要一个配置 XML,来告诉它如何连接到数据库。在此示例中,我们将文件命名为 'mybatis-config.xml',内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver"value="org.postgresql.Driver" />
                <property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
                <property name="username" value="postgres" />
                <property name="password" value="" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/rockdata/javabook/mybatis/LargeCitiesMapper.xml" />
    </mappers>
</configuration>

注意到此文件末尾的 标签及其内容了吗?这将在下面的部分中解释。

映射器 XML – 简单 SELECT

映射器 XML 文件,告诉 MyBatis 如何将传入的数据库对象映射到 Java 对象。下面是一个映射器 XML 文件的示例,对 largecities 表运行一条简单的 SELECT 查询。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.rockdata.javabook.mybatis.Mapper">
    <select id="selectCities" resultType="org.rockdata.javabook.mybatis.LargeCities">
        SELECT * FROM largecities
    </select>
</mapper>

使用映射器 XML

MyBatis 提供了许多资源,可以很容易地加载 XML 数据和创建输入流。使用映射器 XML 文件读取数据的事件时序如下:

  1. 1. 从映射器 XML 创建输入流
  2. 2. 使用上面的 SqlSessionFactoryBuilder 和 inputStream,创建一个 sqlSessionFactory
  3. 3. 从这个 sessionFactory 打开一个新会话
  4. 4. 调用封装 SQL 查询的 Java 方法

因此,最终代码如下所示:

try  {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    SqlSession session = sqlSessionFactory.openSession();
    List<LargeCities> list = session.selectList("selectCities");

    for (LargeCities a : list) {
        System.out.println("Rank: " + a.getRank() + " Name: " + a.getName());
    }
}
catch (Exception e) {
    e.printStackTrace();
}

请注意,在创建 InputStream 时如何引用 mybatis-config.xml,然后使用 selectCities 的 id(在映射器 XML 中声明)来调用 Java 方法。

此代码的输出如下:

Rank: 1 Name: Tokyo
Rank: 2 Name: Seoul
Rank: 3 Name: Shanghai
Rank: 4 Name: Guangzhou
Rank: 5 Name: Karachi
Rank: 6 Name: Delhi
Rank: 7 Name: Mexico City
Rank: 8 Name: Beijing
Rank: 9 Name: Lagos
Rank: 10 Name: Sao Paulo

传递参数

为了指定提取条件,您可以将参数传递给您的查询。这在映射器 XML 中指定。例如:

<select id="selectCitiesWithInput" resultType="org.rockdata.javabook.mybatis.LargeCities">
    SELECT * FROM largecities where rank < #{rank} 
</select>

在此示例中,将检索排名小于 #{rank} 参数指定值的所有结果。

此方法从 main 函数中调用,如下所示:

List<LargeCities> list = session.selectList("selectCitiesWithInput", 6);

此代码的输出为:

Rank: 1 Name: Tokyo
Rank: 2 Name: Seoul
Rank: 3 Name: Shanghai
Rank: 4 Name: Guangzhou
Rank: 5 Name: Karachi

插入数据

插入数据需要在映射 XML 文档中添加另一个条目。

<insert id="insertCity">
    INSERT INTO largecities (rank, name) VALUES (#{rank},#{name})
</insert>

然后,可以使用以下 Java 代码完成插入:

try  {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    SqlSession session = sqlSessionFactory.openSession();

    LargeCities mumbai = new LargeCities(); 
    mumbai.setRank(11);
    mumbai.setName("Mumbai");

    session.insert("insertCity", mumbai);
    session.commit();

    List<LargeCities> list = session.selectList("selectCities");

    for (LargeCities a : list) {
        System.out.println("Rank: " + a.getRank() + " Name: " + a.getName());
    }
}
catch (Exception e) {
    e.printStackTrace();
}

请注意,在调用会话的 'insert' 方法时,Java 对象是如何自动映射到数据库对象的。

此代码将排名第 11 位的 Mumbai 插入数据库,然后提交事务。代码的输出如下:

Rank: 1 Name: Tokyo
Rank: 2 Name: Seoul
Rank: 3 Name: Shanghai
Rank: 4 Name: Guangzhou
Rank: 5 Name: Karachi
Rank: 6 Name: Delhi
Rank: 7 Name: Mexico City
Rank: 8 Name: Beijing
Rank: 9 Name: Lagos
Rank: 10 Name: Sao Paulo
Rank: 11 Name: Mumbai

更新数据

用于更新数据的映射 XML 中的条目,会如下所示:

<update id="updateCity">
    UPDATE largecities SET name = #{name} WHERE rank = #{rank}
</update>

在我们的 Java 代码中,可以这样使用此映射:

LargeCities newYork = new LargeCities(); 
newYork.setRank(11);
newYork.setName("New York");

session.insert("updateCity", newYork);
session.commit();

List<LargeCities> list = session.selectList("selectCities");  

for (LargeCities a : list) {
    System.out.println("Rank: " + a.getRank() + " Name: " + a.getName());
}

同样,请注意,Java 对象会根据我们的映射 XML 自动映射到数据库对象。

该程序的输出为:

Rank: 1 Name: Tokyo
Rank: 2 Name: Seoul
Rank: 3 Name: Shanghai
Rank: 4 Name: Guangzhou
Rank: 5 Name: Karachi
Rank: 6 Name: Delhi
Rank: 7 Name: Mexico City
Rank: 8 Name: Beijing
Rank: 9 Name: Lagos
Rank: 10 Name: Sao Paulo
Rank: 11 Name: New York

删除数据

现在,让我们专注于删除我们插入并更新的第 11 个条目。映射 XML 代码如下所示:

<delete id="deleteCity">
    DELETE FROM largecities WHERE rank = #{rank}
</delete>

Java 代码将按如下方式使用此映射:

LargeCities newYork = new LargeCities(); 
newYork.setRank(11);
newYork.setName("New York");

session.insert("deleteCity", newYork);
session.commit();

List<LargeCities> list = session.selectList("selectCities");  

for (LargeCities a : list) {
    System.out.println("Rank: " + a.getRank() + " Name: " + a.getName());
}

输出内容现在返回到了,我们开始时原始的表数据:

Rank: 1 Name: Tokyo
Rank: 2 Name: Seoul
Rank: 3 Name: Shanghai
Rank: 4 Name: Guangzhou
Rank: 5 Name: Karachi
Rank: 6 Name: Delhi
Rank: 7 Name: Mexico City
Rank: 8 Name: Beijing
Rank: 9 Name: Lagos
Rank: 10 Name: Sao Paulo

使用 MyBatis 的缺点

由于 MyBatis 以数据库为中心的方法,它不太适合于以对象为中心设计的应用程序。此外,虽然 MyBatis 在数据检索方面非常出色,但对于复杂的领域实体,执行写入操作可能会变得相当繁琐。

MyBatis 被设计为直接使用 SQL,因此在使用此框架时,你不能不编写 SQL。由于这种低级别控制,任何数据库的更改都需要对 Java 代码进行手动干预。

此外,由于您将自己编写 SQL,因此运行时错误的可能性始终存在。Java 编译器将无法捕获 SQL 中的错误,并且您的应用可能会抛出非描述性的 JDBC 错误。

责任编辑:武晓燕 来源: 红石PG
相关推荐

2015-04-08 10:40:09

2023-12-04 06:55:16

2013-06-26 10:49:09

云端大脑科技技术

2009-08-02 22:32:44

综合布线系统

2020-09-23 08:55:16

交换机配置网络vlan

2019-05-13 15:45:29

程序员面试招聘

2022-10-30 15:03:25

人工智能仓库管理机器人

2013-12-25 09:07:24

微软鲍尔默诺基亚

2012-06-18 09:33:03

云计算IBM惠普

2009-10-26 13:36:10

BSM

2019-01-22 10:58:07

2013-01-31 11:51:37

开源KVM

2019-04-26 13:59:10

网络VLAN虚拟局域网

2013-02-27 10:53:16

开源KVM

2017-02-08 10:01:13

大数据ETL技术

2015-10-10 13:50:29

IT设备PDU

2017-07-27 16:25:54

云管理公共云合并

2017-12-17 16:53:27

云计算亚马逊云端

2019-01-11 10:39:24

软件架构虚拟空间机器人
点赞
收藏

51CTO技术栈公众号