Facebook Twitter LinkedIn E-mail
magnify
Home Posts tagged "Java"

一个使用sbt编译的JNI C++ 的模板

如果你需要在Scala或是Java中调用C或C++函数库,就需要使用JNI, 这里就涉及到编译scala ,java 和C(C++)代码,在这里给出一个程序的框架,我们使用sbt 缺省的代码目录

文件目录
src
—>main
——–>java
——–>scala
——–>c

其中目录c存放C++代码 ,java目录放置Java代码, scala目录放置Scala代码

项目组用来编译的相关文件为build.sbt 和Makefile (它编译放置在c目录下的C++文件,注意只能编译C++,如果你有需要编译C,需要自行修改Makefile)

修改库文件名为自己所需的名称
修改build.sbt 中的项目名称

name := "JNIDemo"

version := "0.0.1-SNAPSHOT"

organization := "com.guidebee"

修改Makefile的库文件名称

#### PROJECT SETTINGS ####
# The name of the executable to be created
SODIR = target/so
BIN_NAME= $(SODIR)/libjnidemo.so

修改Java引用的库文件名称:

static {
    System.loadLibrary("jnidemo");
  }

设置环境变量
在你设置好sbt的编译环境后,注意设置 JAVA_HOME 和 LD_LIBRARY_PATH 环境变量 ,Java_HOME为你Java的安装目录, 可以使用
export LD_LIBRARY_PATH = $LD_LIBRARY_PATH:./:./target/so
将编译后的库文件添加到 java.library.path 路径中(这样Java代码可以找到库文件所在目录)

编译和运行
编译使用指令 sbt compile

root@ubuntu:/sdb/jni# sbt compile
[info] Set current project to JNIDemo (in build file:/mnt/sdb1/jni/)
[info] Compiling 3 Java sources to /mnt/sdb1/jni/target/scala-2.10/classes...
Creating directories
Beginning release build
Compiling: src/main/c/IntArray.cpp -> build/release/IntArray.o -Wall -Wextra -g -fPIC -c -O -m64 -Wunused-parameter
src/main/c/IntArray.cpp:21:1: warning: unused parameter ‘obj’ [-Wunused-parameter]
 Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
 ^
         Compile time: 00:00:00
Compiling: src/main/c/Prompt.cpp -> build/release/Prompt.o -Wall -Wextra -g -fPIC -c -O -m64 -Wunused-parameter
src/main/c/Prompt.cpp: In function ‘_jstring* Java_Prompt_getLine(JNIEnv*, jobject, jstring)’:
src/main/c/Prompt.cpp:24:13: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
   char *buf="hello";
             ^
src/main/c/Prompt.cpp: At global scope:
src/main/c/Prompt.cpp:22:1: warning: unused parameter ‘obj’ [-Wunused-parameter]
 Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
 ^
         Compile time: 00:00:00
mkdir target/so
Linking: target/so/libjnidemo.so
#@g++ build/release/IntArray.o build/release/Prompt.o  -fPIC    -o target/so/libjnidemo.so
         Link time: 00:00:00
Making library: target/so/libjnidemo.so -> target/so/libjnidemo.so
Total build time: 00:00:00
[success] Total time: 1 s, completed 29/08/2014 10:10:19 PM

运行
sbt run

root@ubuntu:/sdb/jni# sbt run
[info] Set current project to JNIDemo (in build file:/mnt/sdb1/jni/)
[info] Running Test 
[info] User typed: hello
[info] sum = 45
[info] Type a line: 
[success] Total time: 0 s, completed 29/08/2014 10:10:54 PM

删除编译结果
sbt clean

root@ubuntu:/sdb/jni# sbt clean
[info] Set current project to JNIDemo (in build file:/mnt/sdb1/jni/)
[info] Updating {file:/mnt/sdb1/jni/}jni...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
Deleting target/so/libjnidemo.so symlink
Deleting directories
[success] Total time: 1 s, completed 29/08/2014 10:11:35 PM

Github 代码
本例模板代码可以在 https://github.com/guidebee/JNIDemo下载。

20140829001

 

Hibernate开发教程(2):准备开始

使用Hibernate开发应用,一种方法是下载Hibernate相关的jar文件,然后再项目在添加引用。由于Hibernate涉及的库比较多,这种方法比较麻烦,因此本教程使用Maven来管理项目。关于Maven的简单教程可以参见:

  1. Maven 使用指南(1): 概述
  2. Maven 使用指南(2): 第一个例子Hello World
  3. Maven 使用指南(3): 简述Maven工作过程
  4. Maven 使用指南(4): Maven Build 的阶段
  5. Maven 使用指南(5): Maven 自动依赖管理
  6. Maven 使用指南(6): 使用Maven插件
  7. Maven 使用指南(7): 使用Maven打包资源文件
  8. Maven 使用指南(8): 使用Maven管理多个项目

此外教程采用MySql 数据库为例,如果你使用Windows操作系统,可以安装WAMP系统(包括MySQL,Apache ,PHP等)也可以只安装MySQL。 Hibernate 使用其它数据库的方法大同小异。

管理MySQL的免费前端管理工具为HeidiSQL,你也可以使用命令行或是其它工具。

开始使用的示例数据库为Sales 数据库,可以参见Vaadin Web应用开发教程(46): 开始使用SQLContainer 。或是本地下载Sales.sql.

此外为方便起见 使用 Maven-Hibernate3插件,可以直接从数据库生成 映射文件和Java类代码。具体使用可以参见 Mojo。

开发环境使用Eclipse 或是 SpringSouce tool Suite (STS),这些都可以从网上免费下载。

首先创建一个Maven项目 HibernateTutorial.

修改pom.xml 添加于Hibernate相关的引用:

<dependencies>
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-core</artifactId>
		<version>4.1.6.Final</version>
	</dependency>

	<!-- Hibernate uses jboss-logging for logging, for the tutorials we will
		use the sl4fj-simple backend -->
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-simple</artifactId>
		<version>1.6.1</version>
	</dependency>

	<!-- The tutorials use JUnit test cases to illustrate usage -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.10</version>
	</dependency>

	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.0.8</version>
	</dependency>
</dependencies>

使用Maven-Hibernate 的 hbm2java (自动生成Java代码),hbm2hbmxml (自动生成.hbm.xml 映射文件) 和 hbm2cfgxml (自动生成最终的hibernate.cfg.xml文件)

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>hibernate3-maven-plugin</artifactId>
	<version>2.2</version>
	<configuration>
		<components>
			<component>
				<name>hbm2java</name>
				<outputDirectory>src/main/java/</outputDirectory>
				<implementation>jdbcconfiguration</implementation>
			</component>

			<component>
				<name>hbm2hbmxml</name>
				<outputDirectory>src/main/resources/</outputDirectory>
			</component>

			<component>
				<name>hbm2cfgxml</name>
				<outputDirectory>src/main/resources/</outputDirectory>
				<implementation>jdbcconfiguration</implementation>
			</component>
		</components>

		<componentProperties>
			<drop>true</drop>

			<configurationfile>/src/main/resources/hibernate.cfg.xml</configurationfile>
			<packagename>com.pstreets.hibernate.demo.data</packagename>
		</componentProperties>
	</configuration>
	<dependencies>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.0.8</version>
		</dependency>

	</dependencies>
</plugin>

其中hbm2java 通过 outputDirectory参数指明创建的Java代码的目录,hbm2hbmxml通过outputDirectory参数指明创建的映射文件的目录,本例使用缺省的资源目录src/main/resources ,因为我们使用MySQL plugin也添加了对mysql 的依赖。

hibernate.cfg.xml 为Hibernate的配置文件,本例使用如下配置来连接Mysql数据库的Sales数据库

<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">password</property>
<property name="hibernate.connection.pool_size">1</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/Sales</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>

在命令行运行 mvn hibernate3:hbm2java hibernate3:hbm2cfgxml hibernate3:hbm2hbmxml 自动生成java代码,.hbm.xml 映射文件及配置文件hibernate.cfg.xml。

到此时我们还没有写过一行代码。

下面我们就使用Hibernate 来读取Sales数据库的Customer表,并显示所有Customer的FirstName 和Last Name,代码如下:

SessionFactory sessionFactory;
sessionFactory = new Configuration().configure().buildSessionFactory();

// create a couple of events...
Session session = sessionFactory.openSession();
session.beginTransaction();

List result = session.createQuery( "from Customer" ).list();
for ( Customer customer : (List<Customer>) result ) {
	System.out.println( "Customer: " + customer.getFirstName()
	 + " " + customer.getLastName() );
}
session.getTransaction().commit();
session.close();

if (sessionFactory != null) {
	sessionFactory.close();
}

这里先不解释,但可以看出没有任何的SQL语句,就将Customer表的记录写到result 这个List对象中。结果如下:

Customer: Laura Steel
Customer: Susanne King
Customer: Anne Miller
Customer: Michael Clancy
Customer: Sylvia Ringer
Customer: Laura Miller
Customer: Laura White
Customer: James Peterson
Customer: Andrew Miller
Customer: James Schneider
Customer: Anne Fuller
Customer: Julia White
Customer: George Ott
Customer: Laura Ringer
Customer: Bill Karsen
Customer: Bill Clancy
Customer: John Fuller
Customer: Laura Ott
Customer: Sylvia Fuller
Customer: Susanne Heiniger
Customer: Janet Schneider
Customer: Julia Clancy
Customer: Bill Ott
Customer: Julia Heiniger
Customer: James Sommer
Customer: Sylvia Steel
Customer: James Clancy
Customer: Bob Sommer
Customer: Susanne White
Customer: Andrew Smith
Customer: Bill Sommer
Customer: Bob Ringer
Customer: Michael Ott
Customer: Mary King
Customer: Julia May
Customer: George Karsen
Customer: John Steel
Customer: Michael Clancy
Customer: Andrew Heiniger
Customer: Mary Karsen
Customer: Susanne Miller
Customer: Bill King
Customer: Robert Ott
Customer: Susanne Smith
Customer: Sylvia Ott
Customer: Janet May
Customer: Andrew May
Customer: Janet Fuller
Customer: Robert White
Customer: George Fuller

可以下载本例做为后续教程的基础。

 

Hibernate开发教程(1):概述

提起Hibernate,很多人多知道是一个ORM[Object-Relational-Mapping(对象-关系-映射]的中间件。它的设计目标是将软件开发人员从大量相同的数据持久层相关编程工作中解放出来。无论是从设计草案还是从一个遗留数据库开始,开发人员都可以采用Hibernate。Hibernate不仅负责从Java类到数据库表的映射(还包括从Java数据类型到SQL数据类型的映射),还提供了面向对象的数据查询检索机制,从而极大地缩短的手动处理SQL和JDBC上的开发时间。
Hibernate 在.Net Framework 有对应的开发为NHibernate. Hibernate 和NHibernate 的基本概念和使用方法基本一致,因此本教程也可作为NHibernate开发的参考。

首先说明一下为什么要使用ORM工具,也就是使用类似hibernate 等ORM工具的好处。在软件开发的设计的过程,尤其是使用面向对象设计方法时,根据系统需求,抽象出系统对象模型(类定义),有了这些对象类定义,如果需要使用数据库存放这些数据,就需要根据系统需求和类定义来定义数据库的表,定义数据库表时有涉及到表和表之间的关系,表的主键和外键定义等等,然后再通过大量的SQL语句或是通过ADO对象来存取数据库,然后根据数控库内容创建或赋值对应的系统对象的实例。

在开发应用时,开发人员有相当一部分时间花在设计数据库表,表之间的关系,编写SQL语句,使用Hibernate之后,开发人员一般只需要对系统进行建模,抽象出系统的类定义,然后借助Object-Relational 映射文件(一般为XML文件),然后Hibernate就可以自动帮助用户创建数据表,通过简单的save, delete,load, update 等就可以完成数据库的存取操作,而无需再编写大量的SQL代码 ,大大提高软件的开发效率。

学习Hibernate 的一个核心问题为定义对象-关系-映射文件 (Object-Relational Mappings)。如果是开发新系统,有工具可以直接从UML生成Hibernate使用的映射文件。但如果是对现有系统进行改造或是数据库已经定义好,根据已有的系统类Classes 和Database Schema来定义Hibernate 映射文件就需要比较深入的了解Hibernate支持的映射关系类型(有点类似逆向工程,就比较费事)。

对于新建系统,Hibernate可以自动根据映射文件创建数据库Schema ,工作量就小多了,如果使用UML,连创建映射文件的工作都可以省了。

用个简单的例子来说明,比如使用SQL语句插入一条记录。

INSERT INTO Items(id, name) VALUES(NULL, 'My Item');

如果使用ORM框架,可以直接使用对象save方法

Item item = new Item();
item.name = "My Item";
item.save();

ORM框架自动根据所管理的数据创建对应的SQL语句对数据库进行读写操作。
后面就详细介绍Hibernate开发,数据使用常用的MySQL 数据库,Hibernate 支持大部分常用的数据库类型如Oracle, Mysql, Sqlite, SqlServer ,因此使用Hibernate的还有一个好处是通过了一个数据抽象层,可以屏蔽对实际物理数据库类型的依赖,支持无缝更换数据库类型:)(当然还是需要修改一些配置文件)。

 

Maven 使用指南(8): 使用Maven管理多个项目

可以使用Maven来管理多个项目,首先是添加一个父pom.xml 文件,在所需管理项目的上一级,还是以hibernate tutorial 项目为例:

其中父pom.xml 的packaging 必须为 pom 类型

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
    http://maven.apache.org/xsd/maven-4.0.0.xsd" 
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.hibernate.tutorials</groupId>
  <artifactId>hibernate-tutorials</artifactId>
  <version>4.1.6.Final</version>
  <packaging>pom</packaging>
  <name>Hibernate Getting Started Guide Tutorials</name>
  <description0>
     Aggregator for the Hibernate tutorials presented in the Getting Started Guide
 </description>
  <modules>
    <module>basic</module>
    <module>annotations</module>
    <module>entitymanager</module>
    <module>envers</module>
  </modules>
  <properties>
    <maven.deploy.skip>true</maven.deploy.skip>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>4.1.6.Final</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.6.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.2.145</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
  <repositories>
    <repository>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <id>central</id>
      <name>Maven Repository Switchboard</name>
      <url>http://repo1.maven.org/maven2</url>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <id>central</id>
      <name>Maven Plugin Repository</name>
      <url>http://repo1.maven.org/maven2</url>
    </pluginRepository>
  </pluginRepositories>
  <build>
    <plugins>
       ....
    </plugins>
  </build>
  <reporting>
    ...
  </reporting>
</project>

此时可以把需管理的项目的共用的dependencies ,plugin 移动到这个父pom.xml ,然后使用modules 添加到父pom.xml 中。

修改子项目的pom.xml ,添加一个parent 元素。比如 basic 项目的 pom.xml

project xmlns="http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
   http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.hibernate.tutorials</groupId>
        <artifactId>hibernate-tutorials</artifactId>
        <version>4.1.6.Final</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>hibernate-tutorial-hbm</artifactId>
    <name>Hibernate hbm.xml Tutorial</name>
    <description>
	   Hibernate tutorial illustrating the use of native APIs and hbm.xml for mapping metadata
	</description>

    <properties>
        <!-- Skip artifact deployment -->
        <maven.deploy.skip>true</maven.deploy.skip>
    </properties>

</project>

如果使用eclipse IDE ,就更简单了,直接通过modules 来管理模块:

本文是Maven系列教程最后一篇。

 

Maven 使用指南(7): 使用Maven打包资源文件

使用Maven 打包资源文件无需修改pom.xml ,对于一般的Maven项目,Maven 通过标准的文件目录结构来搜寻资源文件,自动将其打包到最终的jar, war包中。

Maven将所有存放在目录${basedir}/src/main/resources 下的所有文件及其目录原封不动的大包到Jar包中,

例如,修改Maven 使用指南(2): 第一个例子Hello World ,在main 目录下创建一个resources 目录,然后创建一个META-INF子目录,在META-INF目录下添加一个application.resources 文件。

然后再命令行使用mvn package 在target 目录下生成HelloWorld-1.0-SNAPSHOT.jar,解压这个文件,可以看到application.resources 文件中目录META-INF目录下:

可以看到META-INF 目录下还有其它一些文件,是有Maven生成的,对于MANIFEST.MF你可以使用自定义的MANIFEST.MF,如果没提供,Maven自动生成一个。

在test 目录中也可以添加resources 目录来使用资源。然后使用如下类似代码来访问资源

// Retrieve resource
InputStream is = getClass().getResourceAsStream( "/application.properties" );

// Do something with the resource

 

Maven 使用指南(6): 使用Maven插件

Maven 使用指南(4): Maven Build 的阶段时介绍过Maven的阶段命令最终是通过Maven的插件来运行的。

Maven采用插件方式的好处是灵活(可以配置),可以扩展(可以开发插件以满足项目Build的需求,比如编译打包项目后,可以通过插件将应用部署到远程服务器等)。

Maven预先定义了很多插件,可以参见http://maven.apache.org/plugins/ ,如果需要另外开发插件,可以参见http://maven.apache.org/plugin-developers/index.html

在Maven中使用插件是通过在pom.xml 中使用plugins 定义,比如 修改缺省的compiler 插件使用Java编译的版本。

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.0.2</version>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>
</build>

可以看出使用plugin 的方法和定义依赖的非常类似,其中configuration部分用来配置插件参数。具体可以参见插件文档

Mavne的插件分为两类:

  • Build plugins  在Build生命周期中执行,必须定义在<build/>元素下.
  • Reporting plugins 在生产site阶段运行,定义在<reporting/> 元素。

和定义依赖一样,使用插件也必须定义groupIdartifactId 和version。