当前位置:编程学习 > JAVA >>

<原创>用Java枚举类定义表,并且生成查询语句。

如何定义一个Student表,包含姓名、年级、班级等数据?

用枚举类可以写得一目了然!代码如下:

enum Student {
    Name(Type.CHAR, 3),
    Grade(Type.NUMBER, 2),
    Class(Type.NUMBER, 2), 
    Lesson(Type.VARCHAR, 12),
    Score(Type.NUMBER, 2), ;

    Type type;
    int length;

    Student(Type _type, int _length) {
        type = _type;
        length = _length;
    }
}



其中的数据类型可以再定义一个枚举类:

enum Type {
    CHAR, VARCHAR, NUMBER, SMALLINT;
}


接着就是本文的重点了,生成SQL语句:

public class NewTest {
    public static void main(String[] args) {
        String sql = "CREATE TABLE " + Student.class.getName() + "{\n";
        for (Student s : Student.values()) {
            sql += "\t" + s + " ";
            sql += s.type;
            sql += "(" + s.length + "),\n";
        }
        sql += "}";
        System.out.println(sql);
    }
}


运行结果:
CREATE TABLE Student{
    Name CHAR(3),
    Grade NUMBER(2),
    Class NUMBER(2),
    Lesson VARCHAR(12),
    Score NUMBER(2),
}


可以看出生成的CREATE最后多一个空格,我们可以进一步完善。
这里只是抛砖引玉,其实我们可以如法炮制,生成Insert,update等语句。

还可以通过这样的方法我们可以自己写一个简单的类似ORM的框架。 --------------------编程问答-------------------- 送分都没人要? --------------------编程问答-------------------- 接分,平时写代码我最喜欢用枚举了,能让代码清晰很多 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 支持J王,我也写过类似的东东,用枚举果然更加强大清晰,期待J王的ORM框架。 --------------------编程问答-------------------- 我也实现过,并且还实现了内存对象用sql语句查询和一些不同数据库版本的字段类型和sql语句的匹配等,现在在考虑通过io操作动态异步更新库表结构,以及优化这种形式的内存记录集的索引。 --------------------编程问答-------------------- 支持,但是为啥ORM都是针对数据库表的呢?
我觉得针对大型项目应该更进一步,把项目从这个层面分为两层,一边负责UI,一边负责业务模型的提供,UI组的开发不能直接接触数据库表,甚至连这个表在java中的映射也不能操作,只能调用封装出来的API。
尤其对于银行业务,UI组得到一个API,做业务开发的时候先根据卡号,客户号,证件号之类的线索获取到一个客户对象,这个客户对象是个树型结构,依次可以迭代所有卡片,账户,交易等等,至于他们之间的关联和逻辑由业务模型组完成,UI组只需要拿来用。
客户对象不仅仅操作表,更主要的是和银行后端纷繁复杂的交易接口前置对接,把这些进行ORM映射,实施cache,集群负载,统一接口方式。
从另外一个角度来说,业务模型组的成果可以被这个银行的多个项目组共享,管理上,业务模型的开发独立成一个项目,业务模型从客户对象开始,很多访问可以被cache,整体业务规则一致,避免两个业务系统在同一个业务流程上执行了不同的业务规则。

哎,,,上来发发牢骚,项目的利润空间太小了,被业务压的闯不过气来,根本没办法实施这个想法! --------------------编程问答-------------------- 这应该写到博客里。。。 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 6 楼  的回复:
我也实现过,并且还实现了内存对象用sql语句查询和一些不同数据库版本的字段类型和sql语句的匹配等,现在在考虑通过io操作动态异步更新库表结构,以及优化这种形式的内存记录集的索引。

想法很好!

引用 7 楼  的回复:
支持,但是为啥ORM都是针对数据库表的呢?
我觉得针对大型项目应该更进一步,把项目从这个层面分为两层,一边负责UI,一边负责业务模型的提供,UI组的开发不能直接接触数据库表,甚至连这个表在java中的映射也不能操作,只能调用封装出来的API。
尤其对于银行业务,UI组得到一个API,做业务开发的时候先根据卡号,客户号,证件号之类的线索获取到一个客户对象,这个客户对象是个树型结构,依次可以迭代……

这样定义UI控件也可以啊,只是UI层和持久层之间还有个业务层比较难处理。 --------------------编程问答-------------------- 挺好,勋章哥,你好~ --------------------编程问答-------------------- 支持~这个可以有,正好解决的我一个需求 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 12 楼  的回复:
支持~这个可以有,正好解决的我一个需求


兄弟,啥需求啊?说来听听 --------------------编程问答-------------------- 这样何苦?用注解很容易实现,而且来的方便。你只需要对需要的对象的属性做注解,并且用反射解析出注解生成SQL会更好。不过也顶一下吧 --------------------编程问答-------------------- 看不出你这个有什么优势,劣势倒有一大堆!建议使用楼上的方法,使用 Annotation --------------------编程问答-------------------- 感谢楼主分享,学习了 --------------------编程问答--------------------
引用 15 楼  的回复:
这样何苦?用注解很容易实现,而且来的方便。你只需要对需要的对象的属性做注解,并且用反射解析出注解生成SQL会更好。不过也顶一下吧

不要光说不练,贴代码看看! --------------------编程问答--------------------
引用 16 楼  的回复:
看不出你这个有什么优势,劣势倒有一大堆!建议使用楼上的方法,使用 Annotation

别装B,贴代码! --------------------编程问答--------------------
引用 19 楼  的回复:
引用 16 楼  的回复:

看不出你这个有什么优势,劣势倒有一大堆!建议使用楼上的方法,使用 Annotation

别装B,贴代码!


JPA 自己去看! --------------------编程问答--------------------
引用 19 楼  的回复:
引用 16 楼  的回复:

看不出你这个有什么优势,劣势倒有一大堆!建议使用楼上的方法,使用 Annotation

别装B,贴代码!


这里不是非技术区,我没必要跟你在这装!

另外,在技术区请注意您的言行! --------------------编程问答--------------------
引用 20 楼  的回复:
JPA 自己去看!


看过了,那只是一套标准而已,要庞大的容器支持,这个只用Java 5自带的特性解决一些小范围的问题。 --------------------编程问答-------------------- 在下只对技术感兴趣,用注解写是挺方便。不过反射的太多了,速度真有点……

public class NewTest {
public static void main(String[] args) {
System.out.println(getSql());
}

static String getSql() {
StringBuilder sql = new StringBuilder();
Student2 s = new Student2();

try {
sql.append("CREATE TABLE " + Student2.class.getName() + "(\n");
for (Field f : Student2.class.getDeclaredFields()) {
sql.append('\t');
sql.append(f.getName());
sql.append(' ');
sql.append(f.get(s));

MyAnnotation an = f.getAnnotation(MyAnnotation.class);

if (an.num() > 0) {
sql.append('(');
sql.append(an.num());
sql.append(')');
}

if (an.isPrimaryKey())
sql.append(" PRIMARY KEY");
else {
sql.append(an.canNull() ? "" : " NOT");
sql.append(" NULL");
}
sql.append(",\n");

}
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
sql.append(')');

return (sql.toString());
}
}

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
int num() default 0;

boolean isPrimaryKey() default false;

boolean canNull() default true;
}

class Student2 {
@MyAnnotation(isPrimaryKey = true)
String ID = "INT";

@MyAnnotation(num = 3, canNull = false)
String Name = "CHAR";

@MyAnnotation(num = 2, canNull = false)
String Grade = "NUMBER";

@MyAnnotation(num = 2, canNull = false)
String Class = "NUMBER";

@MyAnnotation(num = 12)
String Lesson = "VARCHAR";

@MyAnnotation(num = 2)
String Score = "NUMBER";
}
--------------------编程问答--------------------
引用 23 楼  的回复:
在下只对技术感兴趣,用注解写是挺方便。不过反射的太多了,速度真有点……
Java code

public class NewTest {
    public static void main(String[] args) {
        System.out.println(getSql());
    }

    static String getSql() {
        ……


不错不错! 用注释的话自己写起来也比较麻烦 --------------------编程问答-------------------- 又见极品,java之王。。。。。。。PS下:(king_of_dotnet)点耐特之王,是他的小号,自问自答自顶,这样的无耻作风,佩服! --------------------编程问答-------------------- 感觉注解annotation更好。 --------------------编程问答-------------------- 正好自己刚刚自学完枚举。
按照楼主的方法,自己练习了一下。写了insert,delete,update方法

package com.sun.demo;

public class Test {

/**
 * @param args
 */
public static void main(String[] args) {
// 定义className变量取得Student类名
String className = Student.class.getName();
className = className.substring(className.lastIndexOf(".")+1);
System.out.println(create(className));
System.out.println(insert(className,"张三",98,"初一二班"));
System.out.println(update(className,"张三",98,"初一二班"));
System.out.println(delete(className,"张三"));
}
//创建student表,字段是name,score,class
public static String create(String className){
String sql = "create table " + className+"{\n";
for(Student s:Student.values()){
sql += s.name()+" "+s.type+"("+s.len+"),\n";
}
sql +="}";
return sql;
}
//向student表插入数据
public static String insert(String className,String name,int score,String c){
String sql = "insert into " + className+" (";
for(Student s:Student.values()){
sql += s.name()+",";
}
sql = sql.substring(0,sql.length()-1);
sql += ") valuse("+name+","+score+","+c;
sql += ");";
return sql;
}

//按照班级修改学生姓名和成绩
public static String update(String className,String name,int score,String c){
String sql = "update " + className+" set(";
sql += Student.Name +"='" + name +"',";
sql += Student.Score +"='" + score +"'";
sql += " where "+Student.Class+"='"+c+"');";
return sql;
}

//按照名字删除学生信息
public static String delete(String className,String name){
String sql = "delete " + className+" where ";
sql += Student.Name +"='" +name+"'";
return sql;
}
}





运行结果:

create table Student{
Name CHAR(2),
Score NUMBER(2),
Class CHAR(5),
}
insert into Student (Name,Score,Class) valuse(张三,98,初一二班);
update Student set(Name='张三',Score='98' where Class='初一二班');
delete Student where Name='张三'

自己偷了一下懒,自己的Student枚举类没定义那么多

package com.sun.demo;

public enum Student {
Name(Type.CHAR,2),Score(Type.NUMBER,2),Class(Type.CHAR,5);
private Student(Type _type,int length){
this.type = _type;
this.len = length;
}
Type type;
int len;
}


自己在练习中发现,如果定义了包。反射出来的类名是com.sun.demo.Student
所以得处理一下才行
总之,楼主让我看了眼界,又温习了一下枚举。 --------------------编程问答--------------------
引用 27 楼  的回复:
正好自己刚刚自学完枚举。
按照楼主的方法,自己练习了一下。写了insert,delete,update方法
Java code

package com.sun.demo;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
       ……

insert方法忘了加引号了。。

补一下

package com.sun.demo;

public class Test {

/**
 * @param args
 */
public static void main(String[] args) {
// 定义className变量取得Student类名
String className = Student.class.getName();
className = className.substring(className.lastIndexOf(".")+1);
System.out.println(create(className));
System.out.println(insert(className,"张三",98,"初一二班"));
System.out.println(update(className,"张三",98,"初一二班"));
System.out.println(delete(className,"张三"));
}
//创建student表,字段是name,score,class
public static String create(String className){
String sql = "create table " + className+"{\n";
for(Student s:Student.values()){
sql += s.name()+" "+s.type+"("+s.len+"),\n";
}
sql +="}";
return sql;
}
//向student表插入数据
public static String insert(String className,String name,int score,String c){
String sql = "insert into " + className+" (";
for(Student s:Student.values()){
sql += s.name()+",";
}
sql = sql.substring(0,sql.length()-1);
sql += ") valuse('"+name+"','"+score+"','"+c+"'";
sql += ");";
return sql;
}

//按照班级修改学生姓名和成绩
public static String update(String className,String name,int score,String c){
String sql = "update " + className+" set(";
sql += Student.Name +"='" + name +"',";
sql += Student.Score +"='" + score +"'";
sql += " where "+Student.Class+"='"+c+"');";
return sql;
}

//按照名字删除学生信息
public static String delete(String className,String name){
String sql = "delete " + className+" where ";
sql += Student.Name +"='" +name+"'";
return sql;
}
}



create table Student{
Name CHAR(2),
Score NUMBER(2),
Class CHAR(5),
}
insert into Student (Name,Score,Class) valuse('张三','98','初一二班');
update Student set(Name='张三',Score='98' where Class='初一二班');
delete Student where Name='张三'
--------------------编程问答-------------------- 支持一下,我是从C#版的链接跳过来的。
PS:为什么你们的sql语句是大括号create table Student{},难道有了新的标准? --------------------编程问答-------------------- 来学习的! --------------------编程问答-------------------- JF走人,楼主好淫 --------------------编程问答--------------------
引用 27 楼  的回复:
正好自己刚刚自学完枚举。
按照楼主的方法,自己练习了一下。写了insert,delete,update方法
Java code

package com.sun.demo;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
       ……


所以说还得动手做

看了半天一直到你这楼才提到楼主代码里的 class name 问题


// Student.class.getName()

改成

Student.class.getSimpleName()
--------------------编程问答-------------------- 看不懂枚举,下来真要好好学习了 --------------------编程问答-------------------- 稍微改了一下,通用于所有实现了 Field 接口的 enum 类型:


public interface Field {
  
  public Type getType();
  
  public int getLength();
}

public enum Type {
  
  CHAR,
  VARCHAR,
  NUMBER,
  SMALLINT,
  ;
}

public enum Student implements Field {

  Name  (Type.CHAR, 3),
  Grade (Type.NUMBER, 2),
  Class (Type.NUMBER, 2), 
  Lesson (Type.VARCHAR, 12),
  Score (Type.NUMBER, 2), 
  ;

  private final Type type;
  private final int length;
  
  Student(Type type, int length) {
    
    this.type = type;
    this.length = length;
  }
  
  @Override
  public Type getType() {
    
    return type;
  }

  @Override
  public int getLength() {
    
    return length;
  }
}

public class SQLGen {
  
  public static void main(String[] args) {
    
    System.out.println(createTable(Student.class));
  }
  
  public static <E extends Enum & Field> String createTable(Class<E> type) {
    
    if( type == null )
      throw new NullPointerException();
    
    StringBuilder builder = new StringBuilder();
    
    builder.append("CREATE TABLE ")
           .append(type.getSimpleName())
           .append("{\n");
    for(E field : Arrays.asList(type.getEnumConstants())) {
    
      builder.append("\t").append(field).append(" ")
             .append(field.getType()).append("(")
             .append(field.getLength()).append("),\n");
    }
    
    return builder.append("}").toString();
  }
}


run:
CREATE TABLE Student{
Name CHAR(3),
Grade NUMBER(2),
Class NUMBER(2),
Lesson VARCHAR(12),
Score NUMBER(2),
}
BUILD SUCCESSFUL (total time: 0 seconds)
--------------------编程问答-------------------- 试问:
如果增加一个字段后,是改代码重新编译好呢,还是只改一下配置文件比较好? --------------------编程问答--------------------
引用 35 楼  的回复:
试问:
如果增加一个字段后,是改代码重新编译好呢,还是只改一下配置文件比较好?

无论哪种都可以通过程序自动完成,开发工作量差不多,当然前提是要对元数据有修改的需求 --------------------编程问答-------------------- 重新学习了Enum,理解更深,记得更牢了
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,