暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

达梦DM7使用mybatis示例

龙山溪笔谈 2019-04-08
4179

       DM7是达梦公司出品的商业数据库,与Oracle高度兼容,是一款大型通用关系型数据库。

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

本系列文章向大家介绍如何在DM7上运行MyBatis。

 

一、环境准备

1、数据库

利用SYSDBA登录,创建一个新用户testsql脚本如下:

--请以SYSDBA登录执行以下脚本

 

-- 创建test用户,用户密码Test12345, 默认表空间为ts_test

-- 创建表空间

CREATE TABLESPACE ts_test DATAFILE 'test.DBF' SIZE 128; 

-- 创建用户

CREATE USER test IDENTIFIED BY "Test12345" DEFAULT TABLESPACE ts_test;

-- 为方便test用户后续操作,直接授予DBA角色权限,生产环境慎用

GRANT DBA TO test; 

 

 

2、Java工程

创建maven工程目录结构如下

mybatis\   项目根目录

src\main\java    存放java源文件

src\main\resources  存放各种配置文件

lib\  存放本地Jar包

pom.xml  maven项目文件

 

注意,从dm7安装目录\drivers\jdbc目录下,将Dm7JdbcDriver16.jar文件复制到lib目录下,系统运行需要用到

 

pom文件中,添加三个依赖项如下:

    <dependencies>

        <dependency>

            <groupId>com.dameng</groupId>

            <artifactId>Dm7JdbcDriver16</artifactId>

            <version>7.6.0.115</version>

            <scope>system</scope>

            <systemPath>

${basedir}/lib/Dm7JdbcDriver16.jar

</systemPath>

        </dependency>

        <dependency>

            <groupId>org.mybatis</groupId>

            <artifactId>mybatis</artifactId>

            <version>3.4.6</version>

        </dependency>

        <dependency>

            <groupId>log4j</groupId>

            <artifactId>log4j</artifactId>

            <version>1.2.17</version>

        </dependency>

    </dependencies>

 

其中Dm7JdbcDriver16scope为system,并且配置systemPath指向lib目录下的Dm7JdbcDriver16.jar文件,这样maven就不会从maven中央仓库查找文件,而是使用本地jar包。

 

 

 

二、CRUD操作

    1、创建示例表

test用户登录,执行以下脚本

--test用户重新登录后,再执行下列脚本

-- 用户信息表

CREATE TABLE t_user

(

    id  INT NOT NULL, --用户标识

    name  VARCHAR(20) NOT NULL, --姓名

    phone VARCHAR(50), -- 手机

    email VARCHAR(50), -- 邮箱

    PRIMARY KEY(id)

);

 

2、建立对应的pojo对象

package org.dmstudy.mybatis.domain;

 

public class User {

 

private Integer id;

private String name;

private String phone;

private String email;

   //getter/setter省略

}

对象属性名与表字段名保持一致,这样方便mybatis自动映射,简化后续代码。

 

3、配置文件

建立resources\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>

<!-- 读取加载配置文件信息 -->

<properties resource="jdbc.properties" />

 

<settings>

<setting name="logImpl" value="LOG4J" />

</settings>

 

<!-- 别名 -->

<typeAliases>

<typeAlias type="org.dmstudy.mybatis.domain.User" alias="User" />

</typeAliases>

 

<!-- 配置环境变量,可以配置多个,有默认值 -->

<environments default="dev">

<environment id="dev">

<transactionManager type="JDBC" />

<dataSource type="POOLED">

<property name="driver" value="${jdbc.driver}" />

<property name="url" value="${jdbc.url}" />

<property name="username" value="${jdbc.username}" />

<property name="password" value="${jdbc.password}" />

</dataSource>

</environment>

</environments>

 

<!-- 配置映射文件 -->

<mappers>

<mapper resource="org/dmstudy/mybatis/crud/dao/UserMapper.xml" />

</mappers>

</configuration>

typeAliases节定义了一个别名User,方便在后续配置参数类型、返回值类型时使用。

使用缺省的dev环境配置,其中transactionManager使用JDBC类型,dataSource使用POOLED方式,数据库连接参数使用外部属性文件内容配置。

resources目录下创建jdbc.properties文件,通过配置文件中的<properties resource="jdbc.properties" >加载,内容如下:

jdbc.driver=dm.jdbc.driver.DmDriver

jdbc.url=jdbc:dm://localhost:5236

jdbc.username=test

jdbc.password=Test12345

    注意:jdbc.url配置中,最后面只有ip地址和端口,不需要添加数据库名、实例名。这里jdbc.username必须使用前面创建表的用户test,不能使用SYSDBA或其他用户,否则会导致找不到表之类的sql错误。

设置<setting name="logImpl" value="LOG4J" >,使用LOG4J日志系统,创建resources\log4j.properties,内容如下:

# Global logging configuration

log4j.rootLogger=DEBUG, stdout

 

# Console output...

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

定义了向标准控制台输出DEBUG级别的日志,可以查看mybatis生成sql语句和执行情况。

 

4、XML映射文件

MyBatis利用Xml映射文件,实现sql语句和Mapper接口方法的映射。在mybati-config.xml文件中,我们配置了一个mapper,对应的resource文件为classpath路径下的org/dmstudy/mybatis/crud/dao/UserMapper.xml文件,其内容如下:

 

<?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.dmstudy.mybatis.crud.dao.UserMapper">

 

<insert id="insert" parameterType="User">

insert into t_user

(id,name,phone,email)

values

(#{id},#{name}, #{phone}, #{email})

</insert>

 

<select id="retrieve" parameterType="int" resultType="User">

select

id,name,phone,email

from t_user

where id = #{id}

</select>

 

<update id="update" parameterType="User">

update t_user

set

name=#{name},phone=#{phone},email=#{email}

where id=#{id}

</update>

 

<delete id="delete" parameterType="int">

delete from t_user

where id = #{id}

</delete>

 

<select id="listAll"  resultType="User">

select

id,name,phone,email

from t_user

</select>

</mapper>

 

在这个xml映射文件中,根节点mapper元素有一个重要属性namespace,按照mybatis文档的建议,该标识应和xml映射文件在classpath下的路径对应保持一致(将文件路径中的”/”替换为”.”,去掉最后的后缀名就得到这个标识)。按这个规则,此处namespace的值设置为"org.dmstudy.mybatis.crud.dao.UserMapper"

mapper节点下,我们还定义了insert,update,delete,select等几种节点,它们分别对应了sql操作中相应的INSERT、UPDATE、DELETE、SELECT四种类型语句,节点的内容是用来生成sql语句的模板。

Insert节点为例,id=”insert” 这个属性用于配置该语句的唯一标识,在对应的namespace中该标识不要重名,采用有意义的命名方法便于理解和记忆。同时由于该id在后面使用中还会对应java接口的方法名,所以命名最好还要符合java方法的命名习惯。

parameterType=“User“ 这个属性配置了执行该语句时提供的参数类型,这里”User”就是在mybatis-config.xml文件中typeAliases中定义的,以简洁的别名表示参数是一个User对象。如果不使用User别名,也可直接指定类全名”org.dmstudy.mybatis.domain.User”

sql模板中values部分使用了 #{id}#{name}等格式。在mybatis中,该部分在生成sql语句时会替换为?,并且该语句会采用PreparedStatement来编译执行,相应的参数值则使用输入参数(User对象)的相应属性来设置。

Select节点中,resultType="User",表示该语句执行后,mybatis会把底层jdbc执行select语句返回的ResultSet中每一行记录都转化为一个User对象。

 

 

5、Mapper接口

创建org.dmstudy.mybatis.crud.dao UserMapper.java文件,内容如下:

package org.dmstudy.mybatis.crud.dao;

import java.util.List;

import org.dmstudy.mybatis.domain.User;

public interface UserMapper {

 

int insert(User user);

User retrieve(int id);

int update(User user);

int delete(int id);

List<User> listAll();

}

按照mybatis的惯例,该接口的全名org.dmstudy.mybatis.crud.dao.UserMapperUserMapper.xml中定义的namespace保持一致,接口中的每个方法与UserMapper.xml中定义的映射语句保持一致。以retrieve方法为例,方法名对应映射语句的id,方法参数int类型与映射语句parameterType一致,方法返回值类型与映射语句的resultType一致。

INSERTUPDATEDELETE类型的sql语句执行后jdbc会返回记录影响行数,对应的java方法返回值如果设为int则可以获取到这个值,用以判断sql语句是否按预期正确执行。

SELECT类型的sql语句执行后jdbc返回的是一个结果集,对于基于主键的查询,能明确返回最多一条记录时,java方法返回值可直接设为java对象(如User);对于基于一般条件查询结果记录数不确定的情况, java方法返回值一般可设置为List类型。

 

6、调用代码

Mybatis对象初始化

参见CrudAppinit方法,首先通过classpath下的mybatis-config.xml文件资源,利用SqlSessionFactoryBuilderbuild出一个SqlSessionFactory对象,后续可以通过这个sqlSessionFactory对象,随时按需打开一个SqlSession对象。而SqlSession则是用来执行sql语句、提交事务等操作的主要对象。

package org.dmstudy.mybatis.crud;

……

public class CrudApp {

 

SqlSessionFactory sqlSessionFactory;

 

public void init() throws IOException {

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

if (sqlSessionFactory == null) {

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

}

}

}

 

 

执行sql操作

在定义xml映射文件和相应的java接口之后,用户无需实现这些接口,可利用sqlSession对象获取这个接口,当某个接口方法被调用时,mybatis会自动将其转换为xml映射文件中定义的sql语句执行。

insert方法为例,代码如下:

public void insert() {

System.out.println("---insert ---");

 

// 新建user对象

User user = new User();

user.setId(1);

user.setName("dmtech");

user.setPhone("400-6489899");

user.setEmail("dmtech@dameng.com");

 

SqlSession sqlSession = sqlSessionFactory.openSession();

try {

// 获取mapper对象

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

// user插入数据库

int cnt = mapper.insert(user);

sqlSession.commit();

System.out.println("成功插入 " + cnt + "条记录! ");

} catch (Exception e) {

System.err.println("insert执行失败 ,原因:" + e.getMessage());

e.printStackTrace();

sqlSession.rollback();

} finally {

sqlSession.close();

}

}

 

执行时,从log4j输出日志,可查看执行过程详细信息

---insert ---

DEBUG [main] - Opening JDBC Connection

DEBUG [main] - Created connection 203849460.

DEBUG [main] - Setting autocommit to false on JDBC Connection [dm.jdbc.driver.DmdbConnection@c267ef4]

DEBUG [main] - ==>  Preparing: insert into t_user (id,name,phone,email) values (?,?, ?, ?)

DEBUG [main] - ==> Parameters: 1(Integer), dmtech(String), 400-6489899(String), dmtech@dameng.com(String)

DEBUG [main] - <==    Updates: 1

DEBUG [main] - Committing JDBC Connection [dm.jdbc.driver.DmdbConnection@c267ef4]

成功插入 1条记录!

DEBUG [main] - Resetting autocommit to true on JDBC Connection [dm.jdbc.driver.DmdbConnection@c267ef4]

DEBUG [main] - Closing JDBC Connection [dm.jdbc.driver.DmdbConnection@c267ef4]

DEBUG [main] - Returned connection 203849460 to pool.

 

首先当open一个新的SqlSession时,mybatis会从连接池中获取一个Connection,注意缺省配置下,该连接池autocommit被设置为false,因此在执行insert语句之后,要记得调用sqlSession.commit,否则数据不会保持到数据库中。

当通过sqlSession获取UserMapper接口,并执行insert(user)方法时,mybatis会根据对应xml映射文件生成PrepareStatement,语句为:insert into t_user (id,name,phone,email) values (?,?, ?, ?),并利用输入user对象的属性,设置参数值。

最后该语句执行后,日志输出Updates: 1,表明该操作影响了记录行数为1,即语句执行成功,插入了1条记录。

为保证事务完整性,以及资源的正确释放,获取sqlSession之后,应该使用try…catch…finally语句块执行,当catch到异常时要记得rollback,在finally中注意close,释放sqlSession资源,对应日志中也可看出,close实际上是将Connection返回到连接池中。


7、完整代码

完成的project工程目录及文件结构如下:

 

 

 

完整的CrudApp.java代码如下

package org.dmstudy.mybatis.crud;

 

import java.io.IOException;

import java.io.InputStream;

import java.util.List;

 

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 org.dmstudy.mybatis.crud.dao.UserMapper;

import org.dmstudy.mybatis.domain.User;

 

public class CrudApp {

 

SqlSessionFactory sqlSessionFactory;

 

public void init() throws IOException {

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

if (sqlSessionFactory == null) {

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

}

}

 

public void insert() {

System.out.println("---insert ---");

 

// 新建user对象

User user = new User();

user.setId(1);

user.setName("dmtech");

user.setPhone("400-6489899");

user.setEmail("dmtech@dameng.com");

 

SqlSession sqlSession = sqlSessionFactory.openSession();

try {

// 获取mapper对象

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

// user插入数据库

int cnt = mapper.insert(user);

sqlSession.commit();

System.out.println("成功插入 " + cnt + "条记录! ");

} catch (Exception e) {

System.err.println("insert执行失败 ,原因:" + e.getMessage());

e.printStackTrace();

sqlSession.rollback();

} finally {

sqlSession.close();

}

}

 

public void retrieve() {

System.out.println("---retrieve ---");

 

int id = 1;

 

SqlSession sqlSession = sqlSessionFactory.openSession();

try {

// 获取mapper对象

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

// 查询user

User user = mapper.retrieve(id);

if (user == null) {

System.out.println("id=" + id + "的记录不存在! ");

} else {

System.out.println("成功获取User对象 。User[id= " + user.getId() + ", name= " + user.getName() + "]");

}

} catch (Exception e) {

System.err.println("retrieve执行失败 ,原因:" + e.getMessage());

e.printStackTrace();

} finally {

sqlSession.close();

}

}

 

public void update() {

System.out.println("---update ---");

 

int id = 1;

SqlSession sqlSession = sqlSessionFactory.openSession();

try {

// 获取mapper对象

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

// 查询user

User user = mapper.retrieve(id);

if (user == null) {

System.out.println("id=" + id + "的记录不存在! ");

return;

}

 

// 修改user.name

String name = user.getName();

if ("dmtech".equals(name)) {

user.setName("DMTECH");

} else {

user.setName("dmtech");

}

int cnt = mapper.update(user);

sqlSession.commit();

System.out.println("成功修改了 " + cnt + "条记录! ");

} catch (Exception e) {

System.err.println("update执行失败 ,原因:" + e.getMessage());

e.printStackTrace();

sqlSession.rollback();

} finally {

sqlSession.close();

}

}

 

public void delete() {

System.out.println("---delete ---");

 

int id = 1;

 

SqlSession sqlSession = sqlSessionFactory.openSession();

try {

// 获取mapper对象

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

// 查询user

int cnt = mapper.delete(id);

sqlSession.commit();

System.out.println("成功删除了" + cnt + "条记录! ");

} catch (Exception e) {

System.err.println("delete执行失败 ,原因:" + e.getMessage());

e.printStackTrace();

sqlSession.rollback();

} finally {

sqlSession.close();

}

}

 

public void listAll() {

System.out.println("--- listAll ---");

 

SqlSession sqlSession = sqlSessionFactory.openSession();

try {

// 获取mapper对象

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

// 查询user列表

List<User> user_list = mapper.listAll();

System.out.println("查询到" + user_list.size() + "条记录! ");

for (User user : user_list) {

System.out.println("User[id= " + user.getId() + ", name= " + user.getName() + "]");

}

} catch (Exception e) {

System.err.println("listAll执行失败 ,原因:" + e.getMessage());

e.printStackTrace();

} finally {

sqlSession.close();

}

}

 

public static void main(String[] args) throws Exception {

 

CrudApp app = new CrudApp();

app.init();

 

// insert

app.insert();

// retrieve

app.retrieve();

// update

app.update();

// list

app.listAll();

// delete

app.delete();

}

}

 

 

 


最后修改时间:2020-06-23 16:27:32
文章转载自龙山溪笔谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论