用数据库表反向生成hiberante实体类
- 格式:docx
- 大小:621.44 KB
- 文档页数:10
如何让java只根据数据库表名⾃动⽣成实体类根据数据库表名⽣成实体类公司⽤的jpa,没有⽤mybatis。
所以也没有⽤mybatis⾃动⽣成。
但有些数据库表字段太多,就想着⼀劳永逸了,连数据库注释都搞上去第⼀种这⾥使⽤的是jdbcTemplate+Junit测试⽣成,⽅式可变。
SpringBoot版本是2.4.4,只需要加上@SpringBootTest就可以了。
不⽤@RunWithpom:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency>代码package com.shinedata.bims.web;import mons.collections.MapUtils;import ng3.StringUtils;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.sql.ResultSet;import java.sql.SQLException;import java.util.HashMap;import java.util.List;import java.util.Map;/*** @ClassName TestController* @Author yupanpan* @Date 2021/4/12 14:24*/@SpringBootTestpublic class TestController {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testpublic void database(){createEntity("1ceping", "t_evaluation_template_info_copy","com.shinedata.bims.entity",false);}/**** @param dataBaseName 数据库名* @param tableName 表名* @param packageName 包名* @param isAddEntitySuffix 类名是否添加Entity后缀 true-添加 false-不添加*/public void createEntity(String dataBaseName,String tableName,String packageName,boolean isAddEntitySuffix){String className=tableName;if(tableName.substring(0,2).equals("t_")){StringBuilder stringBuilder = new StringBuilder(tableName);stringBuilder.replace(0, 2, "");String initialsUpperCase = stringBuilder.substring(0, 1).toUpperCase();className=initialsUpperCase+stringBuilder.substring(1);}className=removeUnderline(className)+(isAddEntitySuffix?"Entity":"");StringBuffer classBuffer=new StringBuffer();classBuffer.append("import java.util.Date;\r\n");classBuffer.append("import java.time.LocalDateTime;\r\n");classBuffer.append("import com.alibaba.fastjson.JSONObject;\r\n");classBuffer.append("import ng.*;\r\n");classBuffer.append("import java.math.*;\r\n");classBuffer.append("import java.sql.*;\r\n");classBuffer.append("import lombok.Data;\r\n\r\n\r\n");classBuffer.append("@Data\r\n");classBuffer.append("public class " + className + " {\r\n\r\n");List<Map> filedMaps = getFiledMaps(dataBaseName, tableName);processAllAttrs(classBuffer,filedMaps);classBuffer.append("}\r\n");markerBean(className,classBuffer.toString(),packageName);}/*** 创建实体类⽂件* @param className 类名(不包含.java⽂件名后缀) 根据表名⾸字母⼤写并去掉开头t_和所有下划线-驼峰命名* @param content 添加的内容(字段注释等)* @param packageName 包名(com.xxx.xxx.xxx)*/public void markerBean(String className, String content, String packageName) {String folder = System.getProperty("user.dir") + "/src/main/java/" + packageName.replace(".","/") + "/";File file = new File(folder);if (!file.exists()) {file.mkdirs();}String fileName = folder + className + ".java";try {File newjava = new File(fileName);FileWriter fw = new FileWriter(newjava);fw.write("package\t" + packageName + ";\r\n");fw.write(content);fw.flush();fw.close();} catch (IOException e) {e.printStackTrace();}}/*** 解析输出属性** @return*/private void processAllAttrs(StringBuffer sb,List<Map> filedMaps) {for (int i = 0; i < filedMaps.size(); i++) {Map map = filedMaps.get(i);String fieldType = MapUtils.getString(map, "fieldType");String fieldName = MapUtils.getString(map, "fieldName");String fieldComment = MapUtils.getString(map, "fieldComment");if(StringUtils.isNotBlank(fieldComment)){sb.append("\t/**\r\n").append("\t* ").append(fieldComment).append("\n").append("\t*/\r\n");}sb.append("\tprivate " + fieldType + " " + fieldName + ";\r\n\r\n");}}/*** 获取表字段信息(列名、类型、注释等)* @param dataBaseName* @param tableName* @return*/private List<Map> getFiledMaps(String dataBaseName,String tableName) {String sql="SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA ='"+dataBaseName+"' AND TABLE_NAME = '"+tableName+"'"; List<Map> tableFieldList = jdbcTemplate.query(sql, new RowMapper<Map>() {@Overridepublic Map<String,String> mapRow(ResultSet resultSet, int rowNum) throws SQLException {Map<String,String> fieldMap = new HashMap();String column_name = resultSet.getString("COLUMN_NAME");setFieldName(column_name.toLowerCase(),fieldMap);String data_type = resultSet.getString("DATA_TYPE");setFieldType(data_type.toUpperCase(),fieldMap);fieldMap.put("fieldComment",resultSet.getString("COLUMN_COMMENT"));return fieldMap;}});return tableFieldList;}private void setFieldName(String columnName, Map fieldMap) {fieldMap.put("fieldName",removeUnderline(columnName));}/*** 去下划线* @param string* @return*/public String removeUnderline(String string){StringBuilder columnNameBuilder=new StringBuilder(string);if(!string.contains("_")){return string;}else {int i = columnNameBuilder.indexOf("_");columnNameBuilder.replace(i,i+1, "").replace(i,i+1,columnNameBuilder.substring(i,i+1).toUpperCase());return removeUnderline(columnNameBuilder.toString());}}private void setFieldType(String columnType,Map fieldMap){String fieldType="String";if(columnType.equals("INT")||columnType.equals("INTEGER")){fieldType="Integer";}else if(columnType.equals("BIGINT")){fieldType="Long";}else if(columnType.equals("DATETIME")){fieldType="Date";}else if(columnType.equals("TEXT")||columnType.equals("VARCHAR")||columnType.equals("TINYTEXT")||columnType.equals("LONGTEXT")){fieldType="String";}else if(columnType.equals("DOUBLE")){fieldType="Double";}else if(columnType.equals("BIT")){fieldType="Boolean";}else if(columnType.equals("FLOAT")){fieldType="Float";}else if(columnType.equals("DECIMAL")){fieldType="BigDecimal";}else if(columnType.equals("DATE")){fieldType="Date";}else if(columnType.equals("TIMESTAMP")){fieldType="LocalDateTime";}else if(columnType.equals("CHAR")){fieldType="Char";}else if(columnType.equals("JSON")){//mysql5.7版本才开始有的fieldType="JSONObject";}fieldMap.put("fieldType",fieldType);}}⽣成的类⽤的lombok,就懒得去搞getset了第⼆种搞的是直接main⽅法运⾏下就⽣成,⼤同⼩异。
Hibernate实体关联关系映射----总结在我看来,Hibernate提供这些映射关系,常⽤就是⼀对⼀和多对⼀,并且在能不⽤连接表的时候尽量不要⽤连接表。
多对多会⽤到,如果⽤到了,应该⾸先考虑底层数据库设计是否合理。
在实际开发中,在Hibernate关联关系之外常常还有另外⼀种选择⽅案,表各⾃作为单表映射,业务逻辑控制外键关系(有时候就是⼀个相关联的列,但不⼀定要加外键约束),这样更加灵活,并且数据的完整性同样有保证。
当然,“单表映射,业务控制外键关系”并不是说Hibernate的实体关联功能是多余的,Hibernate的实体关联的优点很多,随便拿本书都是讲优点,⽤好了会让开发⼈员感觉更⽅便,现在我也是两种⽅案结合使⽤。
⽐如对于不很确定的两个实体,常常选⽤单表关联。
以前在初学Hibernate还没有完全搞清楚这些关联关系的时候,就是⽤单表映射,业务控制外键关系做的,发现没有任何问题,程序同样运⾏得很好。
看了这些是不是后悔浪费时间学习映射关系了?呵呵,Hibernate的OR Mapping是Hibernate的灵魂,我相信Hibernate的创始⼈⽐我们⼀般⼈的理解更深刻。
只有学会了这些才能体会Hibernate设计者的思想。
学⼀个东西,不光⾃⼰写代码,还应该能看懂别⼈的代码才⾏。
因此系统学习这些关联映射还是⼤有必要的。
以上都是我⾃⼰的观点。
欢迎在此交流讨论。
Hibernate在实际项⽬开发中,hbm.xml包括数据库脚本都是通过Xdoclet⽣成的,在此不采⽤Xdoclet的⽬的是为了便于理解这些映射模型。
实体-数据表-映射⽂件三者对⽐看,太直观了。
瞌睡了,暂时先写到此,有新思路了再补上。
-----------------------------------------------------回Hibernate:Hibernate关联关系映射⽬录│├─单向关联│├─│├─│├─│├─│├─│├─│├─│└─└─双向关联├─├─├─├─├─└─。
使用Hibernate Tools逆向生成实体类并解决乱码问题1Eclipse安装配置1.1安装hibernate tools插件首先要看清楚Eclipse版本,然后找到对应Eclipse版本的hibernate tools插件。
如Eclipse Luna (4.4.2)则找到/jbosstools/updates/stable/luna/下载对应的hibernate tools插件,避免安装错误。
打开eclipse,选择“Help”->“安装新软件”->”Add” 输入网址:/jbosstools/updates/stable/luna/从下拉框里找到hibernate tools插件,也可同时选择其他所需要的插件,逐步安装即可。
1.2新建所要生成VO实体类的工程完成后修改工程的build path,加入从Eclipse的hibernate plugins里找到对应jar包,如下:2配置Hibernate Tools2.1Hibernate Configuration File(cfg.xml)保存在工程的src目录下即可,然后下一步:在这里可以选择Hibernate版本。
在配置数据库连接信息时需要注意:Driver class选择用com.mysql.jdbc.Driver;在Connection URL后面加入Unicode连接参数:jdbc:mysql://127.0.0.1 /test?useUnicode=true&characterEncoding=UTF-8&useInformationSchema=true。
这里可以选择同时生成Console Configuration,也可以后面手工生成。
2.2Hibernate Console Configuration打开配置界面如下:在Common标签页面里记得选择“UTF-8”编码。
可以在控制台看到数据库的数据表了。
数据库表反向⽣成(⼀)MyBatis-generator与IDEA的集成在Dao层,通过数据库表反向⽣成,可以节省我们很多的精⼒,把更多的精⼒投⼊复杂的业务中。
数据库表反向⽣成,指的是通过数据库如mysql中的库表schema⽣成dao层读写表的基础代码,包括model(entity)和dao(mapper)。
在本⽂中我先介绍java中mybatis-generator的反向⽣成。
我们在中会介绍django中ORM的反向⽣成。
mybatis-generator的反向⽣成有两种⽅式1)源码打包⽣成mybatis-generator.jar,通过执⾏jar来⽣成代码,然后把代码拷贝到⼯程2)直接跟编辑器集成,例如IDEA。
我们只说明第⼆种⽅式。
1、在IDEA中创建⼀个maven⼯程2、在maven⼯程的pom⽂件中添加mybatis-generator-maven-plugin插件<build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.2</version><configuration><verbose>true</verbose><overwrite>true</overwrite></configuration></plugin></plugins></build>3、在src/main/resources⽬录下创建两个配置⽂件,generatorConfig.xml和generator.propertiesgeneratorConfig.xml⽂件内容请看注释,<table>中配置的是你要扫描的表。
Eclipse中反向生成hibernate实体类+jpa注释2011-01-24一、配置数据源,sqlServer2000数据库1、菜单栏“Window”……,截图如下:2、Database Connecttions右击“new”,选择要使用的数据库,本例中是SQL Server,给数据源随便命名,此处为MedicalInfoDB,然后单击“next”,截图如下:3、单击Drivers一行最后那个按钮,配置数据库驱动:配置驱动类和url等……最后点击“OK”,截图如下:4、点击“OK”之后,配置“General”选项卡,“Optional”选项卡不用管,截图如下,5、然后点击“Next”,核对一下数据源信息,点击“Finish”。
截图如下:6、二、反向生成实体类1、打开eclipse,在顶部菜单栏右击选择“Customize Per……”,截图如下:2、选择之后弹出如下选项卡,选择“Command Groups A vailability”,在下面勾选“Hibernate Code Generation”,然后点击“OK”,截图如下:3、点击“OK”之后会在菜单栏中显示如下图所示最后一个快捷按钮:4、点击按钮右边的小箭头,选择下拉菜单中第二项“Hibernate Code Generation……”,截图如下:5、选中之后,弹出如下窗口,右击“New”一个New_configuration:6、左键单击选中新建的New_configuration,右边出现好多选项卡,截图如下:参数说明:(1)、没用;(2)、选择保存……的位置。
(3)、如果反向生成实体类,则将勾上。
保存实体类的文件夹的位置(可不填写),Reveng.xml最右边的Setup……,点击后“新建”或者“使用已存在的”reveng.xml。
选择保存reveng.xml文件的项目的包,点击“Next”,然后点击,单击选中要使用的数据库,或者数据库的某些表(包括表和视图!!!),点击,然后“Finish”。
在IntellijIDEA下通过Hibernate逆向⽣成实体类前⾔:在IDEA中,通过相关插件,可以利⽤Hibernate逆向⽣成数据表对应的实体类。
具体操作及注意事项见本篇随笔。
1.创建⼀个基于maven的hibernate⼯程。
并在⼯程中添夹hibernate核⼼配置⽂件hibernate.cfg.xml,其⼯程结构如下图所⽰。
其中,hibernate.cfg.xml的配置如下:1<?xml version='1.0' encoding='utf-8'?>2<!DOCTYPE hibernate-configuration PUBLIC3 "-//Hibernate/Hibernate Configuration DTD//EN"4 "/dtd/hibernate-configuration-3.0.dtd">5<hibernate-configuration>6<session-factory>78<!-- 主要三部分配置-->9<!-- 1.配置数据库信息,必须的-->10<property name="connection.url">jdbc:mysql://localhost:3306/hibernatestudy?useUnicode=true&characterEncoding=UTF-8</property>11<property name="connection.driver_class">com.mysql.jdbc.Driver</property>12<property name="ername">root</property>13<property name="connection.password"></property>1415<!-- 2.配置hibernate信息,可选的-->1617<!-- 输出底层的sql语句-->18<property name="hibernate.show_sql">true</property>1920<!-- 对底层sql进⾏格式化-->21<property name="hibernate.format_sql">true</property>2223<!--配置数据的⽅⾔,如mysql中limit24 oracle的rownum-->25<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>2627<property name="hibernate.current_session_context_class">thread</property>2829<!-- 3.把映射⽂件配置到核⼼⽂件中,必须的-->3031</session-factory>32</hibernate-configuration>View Code注意:该配置⽂件中对数据库的相关信息进⾏能配置,在后续逆向⽣成实体类的时候,⼜会⽣成数据库信息,所以建议在使⽤插件⽣成实体类时,将数据库配置信息注释,实体类⽣成完后,在将其打开。
IntellijIDEA通过数据库表⽣成带注解的实体类详细步骤前⾔:idea 功能很强⼤,以前不知道有这样的提升⼯作效率的⽅法,虽然有的⼯具确实可以直接⽣成实体类,mapper⽂件,还有dao接⼝,但是个⼈觉得涉及到复杂业务还是只⽣成实体类⽐较好,后⾯部分就⾃⼰搞定就可以了。
⼀、连接数据库打开项⽬:1、点击右侧的datesource图标,要是没有该图标,请去⾃⾏百度2、点击 + 号3、选择 datasource4、选择 mysql1、填写⼀个连接名,随便填什么都⾏2、不⽤选择,默认就⾏3、填写数据库连接的 IP地址,⽐如本地数据库可以填写:localhost或者127.0.0.14、填写数据库开放的端⼝号,⼀般没设置的话默认都是33065、填写你需要连接的数据库名6、填写数据库的⽤户名7、填写数据库密码8、这⾥会有⼀个驱动需要点击下载,图中是已经下载好了9、填写⾃⼰的数据库连接url,然后可以点击9所在按钮进⾏测试连接,本地连接失败检查是否开启了mysql服务连接好了如上图所⽰,可以看到⾃⼰的数据库和表,选择⼀个表右键,⽹上教程⼀般到这⾥结束,都是选择说Generate POJOs.groovy,然后在弹出窗⼝选择需要⽣成的⽂件夹所在即可。
我选择⼀张表进⾏⽣成⽰例如下:表明去除了“_”然后以驼峰⽅式⽣成了类名,⽽且开始的package 路径也不对,重点是没有注释,没有注释,没有注释!⽹上搜了⼀些⽅法,都不太⾏,要不就是到处报错,没辙只能⾃⼰瞎琢磨。
没想到最后也不难,下⾯就是实现:右键选择表,在选择Generate POJOs.groovy 的下⾯那⼀项:进来只有Generate POJOs.groovy,右键新建另外⼀个⽐如我的叫做:Generate MyPOJOs.groovy,⾥⾯内容如下:import com.intellij.database.model.DasTableimport com.intellij.database.model.ObjectKindimport com.intellij.database.util.Caseimport com.intellij.database.util.DasUtilimport java.io.*import java.text.SimpleDateFormat/** Available context bindings:* SELECTION Iterable<DasObject>* PROJECT project* FILES files helper*/packageName = ""typeMapping = [(~/(?i)tinyint|smallint|mediumint/) : "Integer",(~/(?i)int/) : "Long",(~/(?i)bool|bit/) : "Boolean",(~/(?i)float|double|decimal|real/) : "Double",(~/(?i)datetime|timestamp|date|time/) : "Date",(~/(?i)blob|binary|bfile|clob|raw|image/): "InputStream",(~/(?i)/) : "String"]FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->SELECTION.filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE }.each { generate(it, dir) }}def generate(table, dir) {def className = javaName(table.getName(), true)+"Entity"def fields = calcFields(table)packageName = getPackageName(dir)PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(dir, className + ".java")), "UTF-8")) printWriter.withPrintWriter {out -> generate(out, className, fields,table)}// new File(dir, className + ".java").withPrintWriter { out -> generate(out, className, fields,table) }}// 获取包所在⽂件夹路径def getPackageName(dir) {return dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";"}def generate(out, className, fields,table) {out.println "package $packageName"out.println ""out.println "import javax.persistence.Column;"out.println "import javax.persistence.Entity;"out.println "import javax.persistence.Table;"out.println "import java.io.Serializable;"out.println "import lombok.Getter;"out.println "import lombok.Setter;"out.println "import lombok.ToString;"Set types = new HashSet()fields.each() {types.add(it.type)}if (types.contains("Date")) {out.println "import java.util.Date;"}if (types.contains("InputStream")) {out.println "import java.io.InputStream;"}out.println ""out.println "/**\n" +" * @Description \n" +" * @Author zouhui\n" +" * @Date "+ new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + " \n" +" */"out.println ""out.println "@Setter"out.println "@Getter"out.println "@ToString"out.println "@Entity"out.println "@Table ( name =\""+table.getName() +"\" )"out.println "public class $className implements Serializable {"out.println ""out.println genSerialID()fields.each() {out.println ""// 输出注释if (isNotEmpty(moent)) {out.println "\t/**"out.println "\t * ${moent.toString()}"out.println "\t */"}if (it.annos != "") out.println " ${it.annos.replace("[@Id]", "")}"// 输出成员变量out.println "\tprivate ${it.type} ${};"}// 输出get/set⽅法// fields.each() {// out.println ""// out.println "\tpublic ${it.type} get${.capitalize()}() {"// out.println "\t\treturn this.${};"// out.println "\t}"// out.println ""//// out.println "\tpublic void set${.capitalize()}(${it.type} ${}) {"// out.println "\t\tthis.${} = ${};"// out.println "\t}"// }out.println ""out.println "}"}def calcFields(table) {DasUtil.getColumns(table).reduce([]) { fields, col ->def spec = Case.LOWER.apply(col.getDataType().getSpecification())def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.valuedef comm =[colName : col.getName(),name : javaName(col.getName(), false),type : typeStr,commoent: col.getComment(),annos: "\t@Column(name = \""+col.getName()+"\" )"]if("id".equals(Case.LOWER.apply(col.getName())))comm.annos +=["@Id"]fields += [comm]}}// 处理类名(这⾥是因为我的表都是以t_命名的,所以需要处理去掉⽣成类名时的开头的T,// 如果你不需要那么请查找⽤到了 javaClassName这个⽅法的地⽅修改为 javaName 即可)def javaClassName(str, capitalize) {def s = Util.splitNameIntoWords(str).collect { Case.LOWER.apply(it).capitalize() }.join("").replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")// 去除开头的T /art/200906/129168.htms = s[1..s.size() - 1]capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1]}def javaName(str, capitalize) {// def s = str.split(/(?<=[^\p{IsLetter}])/).collect { Case.LOWER.apply(it).capitalize() }// .join("").replaceAll(/[^\p{javaJavaIdentifierPart}]/, "_")// capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1]def s = Util.splitNameIntoWords(str).collect { Case.LOWER.apply(it).capitalize() }.join("").replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1]}def isNotEmpty(content) {return content != null && content.toString().trim().length() > 0}static String changeStyle(String str, boolean toCamel){if(!str || str.size() <= 1)return strif(toCamel){String r = str.toLowerCase().split('_').collect{cc -> Case.LOWER.apply(cc).capitalize()}.join('') return r[0].toLowerCase() + r[1..-1]}else{str = str[0].toLowerCase() + str[1..-1]return str.collect{cc -> ((char)cc).isUpperCase() ? '_' + cc.toLowerCase() : cc}.join('')}}static String genSerialID(){return "\tprivate static final long serialVersionUID = "+Math.abs(new Random().nextLong())+"L;"}完成后,点击此处,选择project 切换回来:这时,我们再次选择表,右键,选择我们⾃⼰新建的 groovy,然后选择⽣成存放的⽂件夹路径,⽣成:可以看到,⽣成的类名,package路径,以及已经实现了序列化,也加上了注解,指明了每个属性对应的表字段,如果@Table和@Column 没有引⼊包,还请在maven中添加相关依赖:<dependency><groupId>javax.persistence</groupId><artifactId>persistence-api</artifactId><version>1.0.2</version></dependency>。
ideahibernatejpa⽣成实体类的实现本篇博客记录下 IDEA 中连接数据库反转⽣成 Hibernate 实体和配置⽂件。
1. 打开 DataBase 窗⼝,添加数据源到了这⼀步数据源已添加好。
2. 添加 hibernat 持久层⽀持,⽣成实体 Bean /配置⽂件,这⼀步要去plugs那⾥下载⼀个hibernate插件,不然你的persistence是出不来的OK,结束如果你选择⽣成带 JPA 注解类,映射⽂件是可以省略的,相反如果你⽣成映射⽂件,JPA 注解也可以省略。
看你喜欢哪种⽅式⽣成注解例⼦@Entity@Table(name = "user", schema = "db_test", catalog = "")public class UserPO {private String uuid;private String name;private String passwd;private String sex;private Timestamp birthday;private String phone;private String photo;private String email;private String yxbz;private String sorts;@Id@Column(name = "UUID")public String getUuid() {return uuid;}public void setUuid(String uuid) {this.uuid = uuid;}@Basic@Column(name = "NAME")public String getName() {return name;}public void setName(String name) { = name;}@Basic@Column(name = "PASSWD")public String getPasswd() {return passwd;}public void setPasswd(String passwd) {this.passwd = passwd;}@Basic@Column(name = "SEX")public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}@Basic@Column(name = "BIRTHDAY")public Timestamp getBirthday() {return birthday;}public void setBirthday(Timestamp birthday) {this.birthday = birthday;}@Basic@Column(name = "PHONE")public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}@Basic@Column(name = "PHOTO")public String getPhoto() {return photo;}public void setPhoto(String photo) {this.photo = photo;}@Basic@Column(name = "EMAIL")public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Basic@Column(name = "YXBZ")public String getYxbz() {return yxbz;}public void setYxbz(String yxbz) {this.yxbz = yxbz;}@Basic@Column(name = "SORTS")public String getSorts() {return sorts;}public void setSorts(String sorts) {this.sorts = sorts;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;UserPO userPO = (UserPO) o;if (uuid != null ? !uuid.equals(userPO.uuid) : userPO.uuid != null) return false;if (name != null ? !name.equals() : != null) return false;if (passwd != null ? !passwd.equals(userPO.passwd) : userPO.passwd != null) return false;if (sex != null ? !sex.equals(userPO.sex) : userPO.sex != null) return false;if (birthday != null ? !birthday.equals(userPO.birthday) : userPO.birthday != null) return false; if (phone != null ? !phone.equals(userPO.phone) : userPO.phone != null) return false;if (photo != null ? !photo.equals(userPO.photo) : userPO.photo != null) return false;if (email != null ? !email.equals(userPO.email) : userPO.email != null) return false;if (yxbz != null ? !yxbz.equals(userPO.yxbz) : userPO.yxbz != null) return false;if (sorts != null ? !sorts.equals(userPO.sorts) : userPO.sorts != null) return false;return true;}@Overridepublic int hashCode() {int result = uuid != null ? uuid.hashCode() : 0;result = 31 * result + (name != null ? name.hashCode() : 0);result = 31 * result + (passwd != null ? passwd.hashCode() : 0);result = 31 * result + (sex != null ? sex.hashCode() : 0);result = 31 * result + (birthday != null ? birthday.hashCode() : 0);result = 31 * result + (phone != null ? phone.hashCode() : 0);result = 31 * result + (photo != null ? photo.hashCode() : 0);result = 31 * result + (email != null ? email.hashCode() : 0);result = 31 * result + (yxbz != null ? yxbz.hashCode() : 0);result = 31 * result + (sorts != null ? sorts.hashCode() : 0);return result;}}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
Hibernate关联关系映射【实验目标】完成本章的内容以后,您将达到:◆Hibernate中实体的三种状态以及它们的特点和状态的转换◆学会manyToOne、oneToMany 、manyToMany的关系映射。
◆掌握用关系映射操纵关系及要注意的问题第一阶段——练习测试对象的三种状态(transient、persistence、detach)及转换:(ora.sql经过调整,在里面创建了四个sequence fwxx_seq , user_seq , jd_seq , qx_seq需要在映射文件FwUser.hbm.xml中调整如下配置,重新指定sequence为user_seq:<id name="fwuid" column="fwuid"><generator class="native"><param name="sequence">user_seq</param></generator></id>)1、建立测试类HibObjectState(带main方法),首选在main方法中实现添加用户小花的功能,代码如下:(注意注释)package com.bu3g.hib.test;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import com.bu3g.entity.FwUser;import com.bu3g.hib.sessionfactory.HibernateSessionFactory;public class HiObjectState {/***@param args*/public static void main(String[] args) {// TODO自动生成方法存根Session ses = HibernateSessionFactory.getSession();Transaction tx = null;try{tx = ses.beginTransaction();// transientFwUser user = new FwUser();user.setUname("xiaohua");user.setUpass("123");//user is persistenceses.save(user);user.setUpass("555"); //持久对象的变化会同步到数据库的对应的记录mit();ses.close();}catch(Exception e){tx.rollback();}}}运行程序(对象经历两个状态:瞬时状态和持久状态),观察:控制台输出两个sql,分别为:insert (save()方法产生),update语句(在事务提交时,为同步持久对象的修改到数据库而产生的).在pl/sql中查询: select * from tbl_user where uname=’xiaohua’比较它的密码是123,还是5552、继续在main方法中添加如下代码(红色部分:)public static void main(String[] args) {Session ses = HibernateSessionFactory.getSession();Transaction tx = null;try{tx = ses.beginTransaction();// transientFwUser user = new FwUser();user.setUname("xiaohua");user.setUpass("123");//user is persistenceses.save(user);user.setUpass("555"); //持久对象的变化会同步到数据库的对应的记录mit();ses.close();//user is detachuser.setUpass("888"); //游离对象不会与数据库同步}catch(Exception e){tx.rollback();}}在数据库中查询:select * from tbl_user where uname=’xiaohua’看看密码是否为555,如不是想想为什么?3、在main中继续加入代码(红色部分):public static void main(String[] args) {// TODO自动生成方法存根Session ses = HibernateSessionFactory.getSession();Transaction tx = null;try{tx = ses.beginTransaction();// transientFwUser user = new FwUser();user.setUname("xiaohua");user.setUpass("123");//user is persistenceses.save(user);user.setUpass("555"); //持久对象的变化会同步到数据库的对应的记录mit();ses.close();//user is detachuser.setUpass("888"); //游离对象不会与数据库同步//调用session的update()方法,才能将游离对象的变化同步到数据库中,//并且,update()方法执行后,会将游离对象变为持久ses = HibernateSessionFactory.getSession();tx = ses.beginTransaction();//user is persistence//注:在同一事务过程中对同一个持久对象做多次更新,只会发一条updateses.update(user);user.setUname("xiaohua2");//user is transientses.delete(user);//user.setUname("xiaohua3");mit();}catch(Exception e){tx.rollback();}}在数据库中输入select * from tbl_user where uname=’xiaohua2’,看看是否有这条记录,若有再看看密码是否888,思考用户名为什么不为xiaohua3?第二阶段——练习:Jd 和Qx对象间建立多对一和一对多的关联,并将这种关联映射到tbl_jd和tbl_qx的多对一的外键关联上来.一、建立Jd到Qx的多对一的关联,并映射到tbl_jd和tbl_qx的外键关联:即:ManyToOne映射从多方并完成以下任务:1、获取街道”北京大学”及”所在区县”:2、建立“山南区”,建立“和平路”,建立“五四路”,建立“八一路”,将和平路、五四路、八一路划入到山南区删除五四路1-1:建立实体类com.bu3g.entity.Qx:package com.bu3g.entity;public class Qx {private int qxid;private String qx;public String getQx() {return qx;}public void setQx(String qx) {this.qx = qx;}public int getQxid() {return qxid;}public void setQxid(int qxid) {this.qxid = qxid;}}1-2:建立实体类com.bu3g.entity.Jd,通过声明Qx类型的成员,建立Jd->Qx的多对一的对象关联:ackage com.bu3g.entity;public class Jd {private int jdid;private String jd;private Qx qx ;public String getJd() {return jd;}public void setJd(String jd) {this.jd = jd;}public int getJdid() {return jdid;}public void setJdid(int jdid) {this.jdid = jdid;}public Qx getQx() {return qx;}public void setQx(Qx qx) {this.qx = qx;}}1-3:在包com.bu3g.entity下建立实体类Qx与表tbl_qx的映射(Qx.hbm.xml):<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "/hibernate-mapping-3.0.dtd" > <hibernate-mapping><class name="com.bu3g.entity.Qx" table="tbl_qx"><id name="qxid" column="qxid"><generator class="native"><param name="sequence">qx_seq</param></generator></id><property name="qx" column="qx"></property></class></hibernate-mapping>1-4:包com.bu3g.entity下建立实体类Jd与tbl_jd的映射(Jd.hbm.xml),并在该映射文件中实现J将d->Qx的多对一的对象关联,映射为表tbl_jd->tbl_qx的外键关联(红色部分) ?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "/hibernate-mapping-3.0.dtd" > <hibernate-mapping><class name="com.bu3g.entity.Jd" table="tbl_jd"><id name="jdid" column="jdid"><generator class="native"><param name="sequence">jd_seq</param></generator></id><property name="jd" column="jd"></property><many-to-one name="qx" class="com.bu3g.entity.Qx"column="qxid" ></many-to-one></class></hibernate-mapping>1-5:映射做好后实现如下功能:从数据库中加载街道”北京大学”,并同时加载它所在的区县:1-5-1:建立ManyToOne类(带main方法),代码如下:package com.bu3g.hib.test;import org.hibernate.Session;import org.hibernate.Transaction;import com.bu3g.entity.Jd;import com.bu3g.entity.Qx;import com.bu3g.hib.sessionfactory.HibernateSessionFactory;public class ManyToOne {/***@param args*/public static void main(String[] args) {// TODO自动生成方法存根ManyToOne test = new ManyToOne();test.test1();}/***获取街道'北京大学',同时得到'北京大学'所在的区县**/public void test1(){Session ses = HibernateSessionFactory.getSession();Jd beijingdaxue = (Jd)ses.get(Jd.class, 2);//Hibernate在查询对象时,同时也自动将对象的关联对象也查询出来System.out.println("街道:"+beijingdaxue.getJd()+",所在区县:"+beijingdaxue.getQx().getQx());}}运行,得到结果:"街道:北京大学,所在区县:海淀区观察控制台中输出的sql语句有哪些,思考它们的作用?.1-5-2:建立testAdd1()成员方法如下,实现前面规定的功能:建立“山南区”,建立“和平路”,建立“五四路”,建立“八一路”,将和平路、五四路、八一路划入到山南区代码如下:public void testAdd1(){Session ses = HibernateSessionFactory.getSession();Transaction tx = null;try{tx = ses.beginTransaction();//增加山南区Qx shangnan = new Qx();shangnan.setQx("山南区");ses.save(shangnan);//增加三个街道:和平路、五四路、八一路Jd heping = new Jd();heping.setJd("和平路");ses.save(heping);Jd wusi = new Jd();wusi.setJd("五四路");ses.save(wusi);Jd bayi = new Jd();bayi.setJd("八一路");ses.save(bayi);//将三个街道加入到山南区,heping.setQx(shangnan);wusi.setQx(shangnan);bayi.setQx(shangnan);mit();}catch(Exception e){if(tx != null){tx.rollback();}e.printStackTrace();}finally{ses.close();}}更改main方法如下:public static void main(String[] args) {// TODO自动生成方法存根ManyToOne test = new ManyToOne();test.testAdd1();}运行,观察控制台中的sql语句,思考它们各自作用?heping.setQx(shangnan); wusi.setQx(shangnan);bayi.setQx(shangnan);三行代码的作用是:将分别将heping、wusi、bayi关联到了区县对象shangnan,思考这三行语句实现的对象关联关系的变化对数据库产生了什么影响?(在数据库中执行四条查询语句:Select * from tbl_qx where qx=’山南区’;Select * from tbl_jd where jd=’和平路’;Select * from tbl_jd where jd=’五四路’;Select * from tbl_jd where jd=’八一路’;)在数据库执行如下sql语句,删除以前插入的数据:(delete from tbl_qx where qx=’山南区’;delete from tbl_jd where jd=’和平路’;delete from tbl_jd where jd=’五四路’;delete from tbl_jd where jd=’八一路’;commit;)1-5-3:建立成员方法testAdd2(),实现与testAdd1()相同功能,但过程做了调整,代码如下:public void testAdd2(){Session ses = HibernateSessionFactory.getSession();Transaction tx = null;try{tx = ses.beginTransaction();//增加山南区Qx shangnan = new Qx();shangnan.setQx("山南区");ses.save(shangnan);//增加三个街道:和平路、五四路、八一路, 并将三个街道加入到山南区 Jd heping = new Jd();heping.setJd("和平路");heping.setQx(shangnan);ses.save(heping);Jd wusi = new Jd();wusi.setJd("五四路");wusi.setQx(shangnan);ses.save(wusi);Jd bayi = new Jd();bayi.setJd("八一路");bayi.setQx(shangnan);ses.save(bayi);mit();}catch(Exception e){if(tx != null){tx.rollback();}e.printStackTrace();}finally{ses.close();}}更改main方法如下:public static void main(String[] args) {// TODO自动生成方法存根ManyToOne test = new ManyToOne();test.testAdd2();}运行,观察的控制台的sql语句输出,发现比testAdd1()少用了三条update语句,效率更高。
Hibernate工程反转(从数据库到实体类)1.增加Hibernate支持2.自动生成hibernate.cfg.xml配置文件,该配置文件为主配置文件(核心)一般一个项目一个。
注意:存放位置不要改变(src目录下),名字也不要改变。
3.选中需要反转的表右键选择hibernate反转(Reverse):创建实体类到数据库表的映射关系4.id主键生成选择native(本地),有数据库决定5.反转完成后自动为我们生成一个映射文件(*.hbm.xml)和一个与之对应的实体类,主配置文件中为我们增加了刚才新生成映射文件的位置映射关系,实体类中每一个属性都与我们反转的数据源数据一一对应,一定要注意映射文件存放的位置(与与之对应实体类存放同一包下)a)*.hbm.xml映射文件解说:i.class节点中属性name:实体类的完整包名类名ii.table:实体类与之对应的在数据库中的表名iii.catalog:该表所属的数据库名iv.换句话说:某个数据库下的某张表与实体类相对应的一个关系(映射关系)v.class下的子节点id:只能有一个,表示的是主键,凡是column相关都是与数据库表字段相关,属性名与数据库字段相对应。
Generator表示的是id主键生成策略,Hibernate强烈建议一般使用native(本地,由数据库决定)6.数据持久化操作(一切开发围绕着数据展开)a)瞬时状态:程序数据存在内存中,程序退出,数据消失。
b)持久状态:程序数据保存在磁盘中,程序退出,数据任然存在。
c)持久化操作:将瞬时状态与持久状态进行转化的机制。
7.数据源:比如数据库、xml、文本文档所存储的数据可以作为数据源。
8.dao:Date access object,数据访问对象,我们写到现在的dao模式(接口)是持久化操作的一个实现,所操作的数据源不仅仅局限于关系型数据库。
我们可以根据不同的数据源编写不同的dao实现,比如说xml、properties等。
hibernate通过数据库表反向生成实体类步骤一:
window-->open Perspective-->MyEclipse Java Persistence
进行了上面的操作后会出现一个视图DB Brower:MyEclipse Derby,
点击右键新建new一个在出现的面板Database Driver中,Driver template中选择
Oracle(ThinDriver)这里以oracle软件为例,如果是mysql就选mysql的
driver name可以随意取,Connection URL就写平常的JDBC中的URL,
jdbc:oracle:thin:@127.0.0.1:1521>]:,用户名,用户密码也是的,接下来add Jars添加oracle 的驱动包,点Test Driver测试下是否可用,点击Finish完成,这时在视图中会出现你写的driver name的那个图标了,点击图标可以看到数据库中所有的表。
步骤二:
选中项目右键-->MyEclipse-->add Hibernate Capabilities
这里我们选择hibernate3.2然后如果需要用到在实体类上添加注释的话那么选中紧挨着的Enable Hibernate Annotations Support
然后下一步选中一个目录存放自动生成hibernate.cfg.xml文件
下一步选中一个DB Driver中我们第一步建立的那个,
然后下一步选中一个目录(选择目录和包)存放自动生成的HibernateSessionFactory工具类
点Finish完成
步骤三:
反转,到DB Brower中那个新建的选中点开到所有表选中并且点击右键--->Hibernate Reverse Enginnering
选中目录存放将要反转出来的实体类并且勾选中Create POJO<>DB(add Hibernate mapping..用来在实体类中添加注释映射,可选可不选),选中Update Hibernate configuration..用来将生成的实体类映射到上一步生成的hibernate.cfg.xml中去,
接着再下一步到typeMapping 这里选中Hibernate type类型,再到Id Generator这里,可以设置成为native,Generate version and timestamp tag是用来在有version字样的数据库列生成表的字段时自动加上@version注解,同样可选可不选,然后点击Finish完成。
就可以回到my eclipse enterprise视图下面看到所生成的实体类以及配置文件。
转自新浪博客的一个技术大神,非常感谢!。