如何为 mysqlcluster 创建休眠配置文件?

Posted

技术标签:

【中文标题】如何为 mysqlcluster 创建休眠配置文件?【英文标题】:How to create hibernate configuration file for mysqlcluster? 【发布时间】:2016-05-17 16:01:29 【问题描述】:

需要 mysql 集群的 Hibernate 配置 (hibernate.cfg.xml) 文件。

[Hibernate] 自动生成 POJO 类和 *.hbm.xml 文件。

我可以使用以下配置访问 Mysql 数据库。

我还可以使用简单的 JDBC 连接访问 MYSQL NDB Cluster 数据库。

问题是当我使用 MYSQL NDB Cluster 数据库凭据时,我无法使用 Hibernate 访问数据库。

请建议使用 Hibernate 配置文件 (hibernate.cfg.xml) 连接 MYSQL NDB Cluster 数据库的任何其他配置。

我认为解决方案是 MySQL NDB 集群 表类型需要新的方言。 否则配置文件中的任何更改

   <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.password">HAZE@rt!f!c!aldb</property>
    <property name="hibernate.connection.pool_size">10</property>
    <property name="hibernate.connection.url">jdbc:mysql://192.168.1.187:3306/haze_videocon_v0.8</property>
    <property name="hibernate.connection.username">haze</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.search.autoregister_listeners">false</property>
    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.validator.apply_to_ddl">false</property>
</session-factory>

【问题讨论】:

【参考方案1】:

必须让 MySQL Cluster 启动并运行。为简单起见,组成集群的所有节点(进程)将与应用程序一起在同一物理主机上运行。

这些是正在使用的 MySQL 集群配置文件:

config.ini:

[ndbd default]noofreplicas=2
datadir=/home/billy/mysql/my_cluster/data

[ndbd]
hostname=localhost
id=3

[ndbd]
hostname=localhost
id=4

[ndb_mgmd]
id = 1
hostname=localhost
datadir=/home/billy/mysql/my_cluster/data

[mysqld]
hostname=localhost
id=101

[api]
hostname=localhost

my.cnf:

[mysqld]
ndbcluster
datadir=/home/billy/mysql/my_cluster/data
basedir=/usr/local/mysql

这侧重于 ClusterJ 而不是运行 MySQL Cluster;如果您是 MySQL 集群的新手,请在尝试之前参考运行一个简单的集群。

ClusterJ 需要被告知如何连接到我们的 MySQL Cluster 数据库;包括连接字符串(管理节点的地址/端口)、要使用的数据库、登录用户以及连接的属性,例如超时值。如果未定义这些参数,则 ClusterJ 将因运行时异常而失败。此信息表示图 3 中所示的“配置属性”。这些参数可以在应用程序代码中进行硬编码,但创建将由应用程序导入的 clusterj.properties 文件更易于维护。此文件应与您的应用程序源代码存储在同一目录中。

clusterj.properties:

com.mysql.clusterj.connectstring=localhost:1186
 com.mysql.clusterj.database=clusterdb
 com.mysql.clusterj.connect.retries=4
 com.mysql.clusterj.connect.delay=5
 com.mysql.clusterj.connect.verbose=1
 com.mysql.clusterj.connect.timeout.before=30
 com.mysql.clusterj.connect.timeout.after=20
 com.mysql.clusterj.max.transactions=1024

由于 ClusterJ 不会自动创建表,下一步是创建“clusterdb”数据库(在 clusterj.properties 中引用)和“employee”表:

[dadaso@ubuntu14-lts-server ~]$ mysql -u root -h 127.0.0.1 -P 3306 -u root
 mysql>  create database clusterdb;use clusterdb;
 mysql> CREATE TABLE employee (
 ->     id INT NOT NULL PRIMARY KEY,
 ->     first VARCHAR(64) DEFAULT NULL,
 ->     last VARCHAR(64) DEFAULT NULL,
 ->     municipality VARCHAR(64) DEFAULT NULL,
 ->     started VARCHAR(64) DEFAULT NULL,
 ->     ended  VARCHAR(64) DEFAULT NULL,
 ->     department INT NOT NULL DEFAULT 1,
 ->     UNIQUE KEY idx_u_hash (first,last) USING HASH,
 ->     KEY idx_municipality (municipality)
 -> ) ENGINE=NDBCLUSTER;

下一步是创建带注释的界面:

Employee.java:

import com.mysql.clusterj.annotation.Column;
import com.mysql.clusterj.annotation.Index;
import com.mysql.clusterj.annotation.PersistenceCapable;
import com.mysql.clusterj.annotation.PrimaryKey;
@PersistenceCapable(table="employee")
@Index(name="idx_uhash")
public interface Employee 
@PrimaryKey
int getId();
void setId(int id);
String getFirst();
void setFirst(String first);

String getLast();
void setLast(String last);
@Column(name="municipality")
@Index(name="idx_municipality")
String getCity();
void setCity(String city);
String getStarted();
void setStarted(String date);
String getEnded();
void setEnded(String date);
Integer getDepartment();
void setDepartment(Integer department);

表的名称在注解@PersistenceCapable(table=”employee”) 中指定,然后employee 表中的每一列都在接口中定义了关联的getter 和setter 方法。默认情况下,接口中的属性名称与表中的列名称相同 - 通过在关联的 getter 方法之前显式包含 @Column(name=”municipality”) 注释来覆盖 City 属性的列名称. @PrimaryKey 注解用于标识关联列是表中主键的属性。 ClusterJ 使用 @Index 注释知道数据库中索引的存在。

下一步是编写我们在此处逐块执行的应用程序代码;其中第一个只包含导入语句,然后加载上面定义的 clusterj.properties 的内容:

Main.java(第 1 部分):

import com.mysql.clusterj.ClusterJHelper;
import com.mysql.clusterj.SessionFactory;
import com.mysql.clusterj.Session;
import com.mysql.clusterj.Query;
import com.mysql.clusterj.query.QueryBuilder;
import com.mysql.clusterj.query.QueryDomainType;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.*;
import java.util.Properties;
import java.util.List;
public class Main 
public static void main (String[] args) throws java.io.FileNotFoundException,java.io.IOException 
// Load the properties from the clusterj.properties file
File propsFile = new File("clusterj.properties");
InputStream inStream = new FileInputStream(propsFile);
Properties props = new Properties();
props.load(inStream);
//Used later to get userinput
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));

下一步是从 ClusterJHelper 类获取 SessionFactory 的句柄,然后使用该工厂创建会话(基于从 clusterj.properties 文件导入的属性。

Main.java(第 2 部分):

// 创建会话(连接数据库) SessionFactory 工厂 = ClusterJHelper.getSessionFactory(props); 会话会话 = factory.getSession(); 现在我们有了一个会话,就可以实例化新的 Employee 对象,然后将它们持久化到数据库中。在没有事务 begin() 或 commit() 语句的情况下,涉及数据库的每个操作都被视为单独的事务。

Main.java(第 3 部分):

/

/ Create and initialise an Employee
Employee newEmployee = session.newInstance(Employee.class);
newEmployee.setId(988);
newEmployee.setFirst("John");
newEmployee.setLast("Jones");
newEmployee.setStarted("1 February 2009");
newEmployee.setDepartment(666);
// Write the Employee to the database
session.persist(newEmployee);

此时,“员工”表中将添加一行。为了验证这一点,创建了一个新的 Employee 对象,并使用 998 的主键 (Id) 值从“employee”表中读取数据:

Main.java(第 4 部分):

// Fetch the Employee from the database
 Employee theEmployee = session.find(Employee.class, 988);
if (theEmployee == null)
 System.out.println("Could not find employee");
else
 System.out.println ("ID: " + theEmployee.getId() + "; Name: " +
 theEmployee.getFirst() + " " + theEmployee.getLast());
 System.out.println ("Location: " + theEmployee.getCity());
 System.out.println ("Department: " + theEmployee.getDepartment());
 System.out.println ("Started: " + theEmployee.getStarted());
 System.out.println ("Left: " + theEmployee.getEnded());

这是此时看到的输出:

ID: 988; Name: John Jones
Location: null
Department: 666
Started: 1 February 2009
Left: null

在我更改员工之前检查数据库 - 完成后点击返回 下一步是修改此数据,但尚未将其写回数据库:

Main.java(第 5 部分):

// Make some changes to the Employee & write back to the database
theEmployee.setDepartment(777);
theEmployee.setCity("London");
System.out.println("Check the database before I change the Employee -
hit return when you are done");
String ignore = br.readLine();

应用程序将在此时暂停,让您有机会检查数据库以确认原始数据已作为新行添加但尚未写回更改:

mysql> select * from clusterdb.employee;
+-----+-------+-------+--------------+-----------------+-------+------------+
| id  | first | last  | municipality | started         | ended | department |
+-----+-------+-------+--------------+-----------------+-------+------------+
| 988 | John  | Jones | NULL         | 1 February 2009 | NULL  |        666 |
+-----+-------+-------+--------------+-----------------+-------+------------+

点击返回后,应用程序将继续并将更改写入表,使用自动事务执行更新。

Main.java(第 6 部分):

session.updatePersistent(theEmployee);
System.out.println("Check the change in the table before I bulk add
Employees - hit return when you are done");
ignore = br.readLine();

应用程序将再次暂停,以便我们现在可以检查更改是否已写回(持久)到数据库:

mysql> select * from clusterdb.employee;
+-----+-------+-------+--------------+-----------------+-------+------------+
| id  | first | last  | municipality | started         | ended | department |
+-----+-------+-------+--------------+-----------------+-------+------------+
| 988 | John  | Jones | London       | 1 February 2009 | NULL  |        777 |
+-----+-------+-------+--------------+-----------------+-------+------------+

然后应用程序继续创建并持久化 100 名新员工。为了提高性能,使用单个事务来在运行 commit() 语句时将所有更改一次写入数据库:

Main.java(第 7 部分):

// Add 100 new Employees - all as part of a single transaction
 newEmployee.setFirst("Billy");
 newEmployee.setStarted("28 February 2009");
session.currentTransaction().begin();
for (int i=700;i<800;i++) 
 newEmployee.setLast("No-Mates"+i);
 newEmployee.setId(i+1000);
 newEmployee.setDepartment(i);
 session.persist(newEmployee);
 
session.currentTransaction().commit();

这 100 名新员工现在将被持久化到数据库中。下一步是创建并执行一个查询,该查询将使用 QueryBuilder 在数据库中搜索部门 777 中的所有员工,并使用它来构建一个 QueryDomain,将“部门”列与参数进行比较。创建后,department 参数设置为 777(随后可以使用不同的部门编号重复使用该查询)。然后应用程序运行查询并遍历并显示结果集中的每个员工:

Main.java(第 8 部分):

// Retrieve the set all of Employees in department 777
QueryBuilder builder = session.getQueryBuilder();
QueryDomainType<Employee> domain =
builder.createQueryDefinition(Employee.class);
domain.where(domain.get("department").equal(domain.param(
"department")));
Query<Employee> query = session.createQuery(domain);
query.setParameter("department",777);
List<Employee> results = query.getResultList();
for (Employee deptEmployee: results) 
System.out.println ("ID: " + deptEmployee.getId() + "; Name: " +
deptEmployee.getFirst() + " " + deptEmployee.getLast());
System.out.println ("Location: " + deptEmployee.getCity());
System.out.println ("Department: " + deptEmployee.getDepartment());
System.out.println ("Started: " + deptEmployee.getStarted());
System.out.println ("Left: " + deptEmployee.getEnded());

System.out.println("Last chance to check database before emptying table
- hit return when you are done");
ignore = br.readLine();

此时,应用程序将显示以下内容并提示用户允许其继续:

ID: 988; Name: John Jones
Location: London
Department: 777
Started: 1 February 2009
Left: null
ID: 1777; Name: Billy No-Mates777
Location: null
Department: 777
Started: 28 February 2009
Left: null

我们可以将该输出与对数据库执行的 SQL 查询进行比较:

mysql> select * from employee where department=777;
 +------+-------+-------------+--------------+------------------+-------+------------+
 | id   | first | last        | municipality | started          | ended | department |
 +------+-------+-------------+--------------+------------------+-------+------------+
 |  988 | John  | Jones       | London       | 1 February 2009  | NULL  |        777 |
 | 1777 | Billy | No-Mates777 | NULL         | 28 February 2009 | NULL  |        777 |
 +------+-------+-------------+--------------+------------------+-------+------------+

最后,再次按回车后,应用程序将删除所有员工:

Main.java(第 9 部分):

session.deletePersistentAll(Employee.class);

作为最后的检查,SQL 查询确认所有行都已从“员工”表中删除。

mysql> select * from employee;
Empty set (0.00 sec)

【讨论】:

以上是关于如何为 mysqlcluster 创建休眠配置文件?的主要内容,如果未能解决你的问题,请参考以下文章

Maven - 如何为休眠添加所有必需的依赖项?

如何为 AVD 管理器创建自定义 Android 设备配置文件?

如何为 AWS RDS 凭证创建配置文件并将其导入我的 AWS Lambda API?

如何为 EmrCreateJobFlowOperator 指定配置文件?

如何为连接表中的其他属性创建多对多 Hibernate 映射?

如何为nginx配置https