本文写的是如何连接上一个现有的H2数据库文件(xxx.mv.db文件)。


注:本文是我亲身操作的,操作绝对没问题,如果在哪个步骤卡住了,请继续往下看完全文看是否能解决

下载


驱动版本说明:
1.3.x版本对应的数据库文件是xxx.h2.db
1.4.x版本对应的数据库文件是xxx.mv.db
对应版本的驱动只能连接或创建对应扩展名的数据库文件,千万不要下错了,我就被版本坑过,下了1.3.x版本的打开xxx.mv.db总是打不开,而且还会新建一个xxx.h2.db的文件。

  1. 打开官网下载地址: http://h2database.com/html/download-archive.html
  2. 点击官网下载页面Maven Central下面的H2 database,然后进入这个页面: https://search.maven.org/search?q=g:com.h2database%20AND%20a:h2&core=gav,选一个进行下载即可。
  3. 下载: 比如我要下载1.4.192版的驱动文件,点击之后访问的是: https://repo1.maven.org/maven2/com/h2database/h2/1.4.192/h2-1.4.192.jar,然后会下载一个'h2-1.4.192.jar'文件,然后记住这个文件的路径。

1.3.x的最高版本是1.3.176,截至2022-05-09的最新驱动是2.1.212,DataGrip可用最新驱动是2.1.210

使用Python连接H2数据库文件

#-*- encoding: utf-8 -*-
def connect_h2_db():
    import jaydebeapi
    dirver = 'org.h2.Driver' # h2 一定要小写
    url = 'jdbc:h2:D:/FCJ/Backup/halo' # 比如数据库文件路径是'jdbc:h2:D:/FCJ/Backup/halo.mv.db',那么就写'jdbc:h2:D:/FCJ/Backup/halo'即可
    username = 'admin'
    password = 'xxxxxx'
    jar = 'D:/FCJ/Backup/h2-1.4.192.jar' # 上面的第3步下载的驱动文件路径
    conn = jaydebeapi.connect(dirver, url, [username, password], jar)
    curs = conn.cursor()
    sql = "这里写你的SQL语句"
    curs.execute(sql)
    print(curs.fetchall())

def main():
    connect_h2_db()

if __name__ == '__main__':
    main()


注意:
'org.h2.Driver'的'h2'一定要小写,我在网上一开始看到的一篇文章写的是'org.H2.Driver',我直接复制过来用结果报错TypeError: Class org.H2.Driver is not found。驱动版本和这个h2大小写的问题害我搞了2个多小时,找了很多办法,自己估摸做了很多尝试了很多次才解决问题😭😭

至此使用Python连接H2数据库就完成了,如果还连接不上,就先尝试一下安装java再次操作,如果还是不行,或者想使用GUI看H2s数据库的内容,往下看。

其他方式查看数据

使用h2自带的网页版连接数据库

比如我上面下载的驱动包是h2-1.4.192.jar,
那么我就到该文件所在的目录(文件夹)中shitf+鼠标右键,选择"在终端中打开"/"在powershell打开",或者打开cmd后cd到该文件所在目录下,执行java -cp h2-1.4.192.jar org.h2.tools.Server -tcpAllowOthers
然后就会自动打开一个网页,url填jdbc:h2:D:/FCJ/Backup/halo,然后填完用户名密码即可连接

注意:
我看网上有很多文章写的是java -cp h2*.jar org.h2.tools.Server -tcpAllowOthers,但是我这么写连不上,需要具体写完整的驱动jar包的包名

DataGrip

  • 注意驱动版本要下载对
  • url: 比如我的db文件路径是:D:/FCJ/Backup/halo.mv.db,那么url就写jdbc:h2:D:/FCJ/Backup/halo

读取数据

正常读取数据是没问题,但有的数据是java class 'org.h2.jdbc.JdbcClob'类型的,这就需要使用到流来读取。

#-*- encoding: utf-8 -*-

def connect_h2_db():
    import jaydebeapi
    dirver = 'org.h2.Driver' # h2 一定要小写
    url = 'jdbc:h2:D:/FCJ/Backup/halo'
    # url = 'jdbc:h2:/root/.halo/db/halo'
    username = 'xxx'
    password = 'xxxxxx'
    jar = 'D:/FCJ/Backup/h2-1.4.192.jar' # 要下载
    conn = jaydebeapi.connect(dirver, url, [username, password], jar)
    curs = conn.cursor()
    sql = "select ID,CREATE_TIME,UPDATE_TIME,EDIT_TIME,FORMAT_CONTENT,ORIGINAL_CONTENT,TITLE from POSTS WHERE FORMAT_CONTENT LIKE '<h1%';"
    curs.execute(sql)
    result_list = curs.fetchall()

    print(f"{len(result_list)}")

    post_list = []
    for i in result_list:
        db_result = i[3]
        print(type(db_result)) # <java class 'org.h2.jdbc.JdbcClob'>
        # print(db_result.__dir__) # 查看对象有哪些属性,哪些方法
        cs = db_result.getCharacterStream()
        ch = 0
        post_char_list = []
        while ch != -1 :
            ch = cs.read()
            if ch != -1:
                char = ' ' if ch==32 else chr(ch)
                char = char.encode("utf-8", 'replace').decode()
                post_char_list.append(char)
                # print(f"{ch}-{char}") # 字符编码转字符
#     print(f"{ch}-{chr(ch)}") # 字符编码转字符
# UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 4: illegal multibyte sequenc
# UnicodeEncodeError: 'utf-8' codec can't encode character '\ud83d' in position 0: surrogates not allowed
# UnicodeEncodeError: 'gbk' codec can't encode character '\ube44' in position 54953: illegal multibyte sequence

            post = ''.join(post_char_list) # 将字符拼接成完整的数据
            post_list.append(post)
        print(f"{len(post_list)}")

        # ['__class__', '__del__', '__delattr__', '__dict__', '__dir__'
        # , '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__'
        # , '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__'
        # , '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__'
        # , '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'
        # , 'equals', 'free', 'getAsciiStream', 'getCharacterStream', 'getClass', 'getSubString'
        # , 'getTraceId', 'getTraceObjectName', 'hashCode', 'length', 'notify', 'notifyAll', 'position'
        # , 'setAsciiStream', 'setCharacterStream', 'setString', 'toString', 'truncate', 'wait']

def main():
    connect_h2_db()

if __name__ == '__main__':
    main()

Q.E.D.


做一个热爱生活的人