Mybatis如何自动生成数据库表结构总结
一般情况下,用Mybatis的时候是先设计表结构再进行实体类以及映射文件编写的,特别是用代码生成器的时候。
但有时候不想用代码生成器,也不想定义表结构,那怎么办?
这个时候就会想到Hibernate,然后想到它的hibernate.hbm2ddl.auto配置项。
所以手工创表的问题可以很方便的迅速用Hibernate来解决。那有人问啦:就是不想用Hibernate才换的Mybatis,你这又兜回去了吗?
其实不是的,我们需要的就是单单一个hbm2ddl功能。
其实应该这么想:有一款工具能够自动根据注解的实体类来生成各种数据库相应的表结构,只需要加几个jar包 (经测试后只要7个)并且少量配置(3个配置项)。
这款工具就是Hibernate。为什么不能是它呢!!!
原理说来也是超级的简单: 加入hibernate的包,注解实体类,程序开始时初始化一下hibernate的SessionFactory并清除它。
示例:
需要的Hibernate相关的JAR包(本例基于Hibernate5.0.7,仅需要7个):
hibernate-core-5.0.7.Final.jar
hibernate-commons-annotations-5.0.1.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar
geronimo-jta_1.1_spec-1.1.1.jar
jboss-logging-3.3.0.Final.jar
dom4j-1.6.1.jar
javassist-3.18.1-GA.jar
Hibernate.cfg.xml文件:(去掉多余的,精简后的内容)
org.hibernate.dialect.MySQL5Dialect update
注解的实体类:
@Entity
@Table(name="t_user")
@Data
@NoArgsConstructor
@ToString
publicclassUserimplementsSerializable{
privatestaticfinallongserialVersionUID=-4013951528313410972L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
privateIntegerid;
@Column(length=30)
privateStringname;
@Column
privateFloatheight;
@Column
privateDoublesalary;
@Column
privateIntegervip;
@Column
@Temporal(TemporalType.DATE)
privateDatebirthday;
@Column
@Temporal(TemporalType.TIMESTAMP)
privateDatelastlogin;
@Column
@Enumerated(EnumType.STRING)
//mybatis默认会将枚举转化为字符串类型存储,此时数据库为varchar型
privateStatestate;
@Column
@Enumerated(EnumType.ORDINAL)
//可以为mybatis设置枚举类型存储为其索引值存储,此时数据库为int型
privateLevellevel;
@Column(length=10)
@Enumerated(EnumType.ORDINAL)
//mybatis自定义类型转换器将枚举转化为相应数字类型存储,此时数据库为int型
privateSexsex;
@Column
@Type(type="string")
//mybatis自定义类型转换器将列表转化为相应字符串类型存储,此时数据库为varchar型
privateListtels;
publicUser(intid){
super();
this.id=id;
}
publicUser(intid,Stringname){
super();
this.id=id;
this.name=name;
}
publicUser(Stringname){
super();
this.name=name;
}
}
注意:以上实体类用了Lombok插件来减少代码量(只要是为了不写setter/getter、toString等。Lombok插件的使用请参考其它地方。)
@Data
@NoArgsConstructor
@ToString
三个注解属于Lombok插件注解,分别指示生成SETTER/GETTER、生成无参构造器、生成ToString
其它注解都属于Hibernate(JPA规范)的注解,生成DDL就靠它们了。
注解-说明:
@Entity @Table(name="t_user") 这里指实体类对应了t_user表 @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id") 这里指表主健自动增长 @Column 这里指表字段名称与属性同名,它可以另外指定长度,名称。 @Temporal(TemporalType.DATE) 这里指表字段采用Date类型存储 @Enumerated(EnumType.STRING) 这里指表字段采用varchar类型来存储枚举属性 这个简短示例仅列出简单的类型的注解,并不涉及表关联之间的注解,幸好的是,注解并不多,更多注解可以参考Hibernate(JPA)注解相关内容。
至此,只需要在使用SqlSessionFactory(Mybatis)之前就构造SessionFactory(Hibernate)然后销毁它就可以了。至于如何初始化Hibernate的SessionFactory,应该都知道。如下:
Mybatis与Spring整合时:简单地配置一个hibernate的SessionFactory相关的BEAN了事。这里不谈。
Mybatis不与Spring整合时:
Mybatis的工具类中添加新方法,用于自动构造DDL:
packagecom.sunwii.mybatis.util;
importjava.io.IOException;
importjava.io.InputStream;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importcom.sunwii.mybatis.constant.Constants;
publicclassSessionFactoryUtil{
publicstaticSqlSessionFactorycreat(StringconfigFile){
SqlSessionFactoryfactory=null;
InputStreaminputStream;
try{
inputStream=Resources.getResourceAsStream(configFile);
factory=newSqlSessionFactoryBuilder().build(inputStream);
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnfactory;
}
//这里是新方法,通过判断标记决定是否要用于自动生成DDL
publicstaticSqlSessionFactorycreat(StringconfigFile,booleanhibernateAutoDdl){
if(hibernateAutoDdl){
StringhibernateConfigFile=Constants.Hibernate_LOCATION;
//使用hibernate自动创建DDL
HibernateUtil.buildSessionFactory(hibernateConfigFile);
}
returncreat(configFile);
}
}
其中用到的Hibernate工具类为:
packagecom.sunwii.mybatis.util;
importjava.util.Properties;
importorg.hibernate.SessionFactory;
importorg.hibernate.cfg.Configuration;
importcom.sunwii.mybatis.constant.Constants;
publicclassHibernateUtil{
publicstaticvoidbuildSessionFactory(StringhibernateConfigFile){
StringjdbcPropertiesLocation=Constants.JDBC_LOCATION;
PropertiesjdbcProperties=PropertiesUtil.loadFromClassPath(jdbcPropertiesLocation);
PropertieshibernateJdbcProperties=newProperties();
hibernateJdbcProperties.setProperty("hibernate.connection.driver_class",jdbcProperties.getProperty("driver"));
hibernateJdbcProperties.setProperty("hibernate.connection.url",jdbcProperties.getProperty("url"));
hibernateJdbcProperties.setProperty("hibernate.connection.username",jdbcProperties.getProperty("user"));
hibernateJdbcProperties.setProperty("hibernate.connection.password",jdbcProperties.getProperty("password"));
finalConfigurationcfg=newConfiguration();
cfg.addProperties(hibernateJdbcProperties);
cfg.configure(hibernateConfigFile);
SessionFactorysessionFactory=cfg.buildSessionFactory();
//启动后销毁
sessionFactory.close();
sessionFactory=null;
}
}
PropertiesUtil工具类:
packagecom.sunwii.mybatis.util;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.Properties;
publicclassPropertiesUtil{
publicstaticPropertiesloadFromClassPath(StringfileName){
Propertiesprops=newProperties();
while(fileName!=null&&fileName.length()>0&&(fileName.startsWith("/")||fileName.startsWith("\\"))){
fileName=fileName.substring(1);
}
InputStreamis=Class.class.getResourceAsStream("/"+fileName);
try{
props.load(is);
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnprops;
}
}
常量配置类Constant:
packagecom.sunwii.mybatis.constant;
publicclassConstants{
publicstaticStringJDBC_LOCATION="jdbc.properties";
publicstaticStringHibernate_LOCATION="hibernate.cfg.xml";
}
Mybatis配置文件:
连接池装饰类(用于简化Mybatis配置并统一jdbc配置文件路径常量):
packagecom.sunwii.mybatis.pool;
importjava.util.Properties;
importorg.apache.ibatis.datasource.pooled.PooledDataSource;
importorg.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
importcom.sunwii.mybatis.constant.Constants;
importcom.sunwii.mybatis.util.PropertiesUtil;
publicclassMyPoolDataSourceFactoryextendsPooledDataSourceFactory{
publicMyPoolDataSourceFactory(){
PooledDataSourcedataSource=newPooledDataSource();
//更多属性可以通过来设置。
StringjdbcPropertiesFile=Constants.JDBC_LOCATION;
Propertiesprop=PropertiesUtil.loadFromClassPath(jdbcPropertiesFile);
dataSource.setDriver(prop.getProperty("driver"));
dataSource.setUrl(prop.getProperty("url"));
dataSource.setUsername(prop.getProperty("user"));
dataSource.setPassword(prop.getProperty("password"));
this.dataSource=dataSource;
}
}
用到的几个枚举类:
packagecom.sunwii.mybatis.enums;
publicenumLevel{
LEVEL_0,
LEVEL_1,
LEVEL_2,
LEVEL_3,
LEVEL_4,
LEVEL_5
}
packagecom.sunwii.mybatis.enums;
importjava.util.HashMap;
publicenumSex{
MAN("男",0),WOMAN("女",1);
privateStringkey;
publicStringgetKey(){
returnkey;
}
publicvoidsetKey(Stringkey){
this.key=key;
}
publicIntegergetValue(){
returnvalue;
}
publicvoidsetValue(Integervalue){
this.value=value;
}
privateIntegervalue;
privatestaticHashMapvalueMap=newHashMap();
privatestaticHashMapkeyMap=newHashMap();
static{
for(Sexitem:Sex.values()){
valueMap.put(item.value,item);
keyMap.put(item.key,item);
}
}
Sex(Stringkey,Integervalue){
this.key=key;
this.value=value;
}
publicstaticSexgetByValue(intvalue){
Sexresult=valueMap.get(value);
returnresult;
}
publicstaticSexgetByKey(Stringkey){
Sexresult=keyMap.get(key);
returnresult;
}
}
packagecom.sunwii.mybatis.enums;
publicenumState{
OK,ERROR,UNKNOWN
}
用到的类型转换器:
packagecom.sunwii.mybatis.typehandle; importjava.sql.CallableStatement; importjava.sql.PreparedStatement; importjava.sql.ResultSet; importjava.sql.SQLException; importorg.apache.ibatis.type.JdbcType; importorg.apache.ibatis.type.TypeHandler; importcom.sunwii.mybatis.enums.Sex; /** *-必须实现所有方法,不然的话查询有可能查询到为null *@authorAdministrator * */ publicclassSexEnumTypeHandlerimplementsTypeHandler{ /** *转换到数据库的值 */ @Override publicvoidsetParameter(PreparedStatementps,inti,Sexparameter,JdbcTypejdbcType)throwsSQLException{ ps.setInt(i,parameter.getValue()); } /** *从数据库转换得到 */ @Override publicSexgetResult(ResultSetrs,StringcolumnName)throwsSQLException{ returnSex.getByValue(rs.getInt(columnName)); } /** *从数据库转换得到 */ @Override publicSexgetResult(ResultSetrs,intcolumnIndex)throwsSQLException{ returnSex.getByValue(rs.getInt(columnIndex)); } /** *从数据库转换得到 */ @Override publicSexgetResult(CallableStatementcs,intcolumnIndex)throwsSQLException{ returnSex.getByValue(cs.getInt(columnIndex)); } }
packagecom.sunwii.mybatis.typehandle; importjava.sql.CallableStatement; importjava.sql.PreparedStatement; importjava.sql.ResultSet; importjava.sql.SQLException; importjava.util.Arrays; importjava.util.List; importorg.apache.ibatis.type.JdbcType; importorg.apache.ibatis.type.TypeHandler; importcom.sunwii.mybatis.util.ArrayUtil; /** *-必须实现所有方法,不然的话查询有可能查询到为null *@authorAdministrator * */ publicclassListTypeHandlerimplementsTypeHandler>{ @SuppressWarnings({"unchecked","rawtypes"}) @Override publicvoidsetParameter(PreparedStatementps,inti,Listparameter,JdbcTypejdbcType)throwsSQLException{ String[]strArr=ArrayUtil.fromList((List
)parameter); Stringstrs=ArrayUtil.asString(",",strArr); ps.setString(i,strs); } @Override publicList getResult(ResultSetrs,StringcolumnName)throwsSQLException{ List list=null; Stringstrs=rs.getString(columnName); if(strs!=null&&strs.length()>0){ list=Arrays.asList(strs.split(",")); } returnlist; } @Override publicList getResult(ResultSetrs,intcolumnIndex)throwsSQLException{ List list=null; Stringstrs=rs.getString(columnIndex); if(strs!=null&&strs.length()>0){ list=Arrays.asList(strs.split(",")); } returnlist; } @Override publicList getResult(CallableStatementcs,intcolumnIndex)throwsSQLException{ List list=null; Stringstrs=cs.getString(columnIndex); if(strs!=null&&strs.length()>0){ list=Arrays.asList(strs.split(",")); } returnlist; } }
用到的数组集合转换工具类:
packagecom.sunwii.mybatis.util;
importjava.lang.reflect.Array;
importjava.util.ArrayList;
importjava.util.Arrays;
importjava.util.Collection;
importjava.util.HashMap;
importjava.util.HashSet;
importjava.util.List;
importjava.util.Map;
importjava.util.Set;
publicclassArrayUtil{
@SuppressWarnings("unchecked")
publicstaticListasList(T...args){
returnArrays.asList(args);
}
publicstaticListasListFromSet(Setset){
if(set==null||set.size()<1){
returnnull;
}
Listlist=newArrayList();
for(Tt:set){
list.add(t);
}
returnlist;
}
publicstaticListasListFromArray(T[]array){
if(array==null||array.length<1){
returnnull;
}
Listlist=newArrayList();
for(Tt:array){
list.add(t);
}
returnlist;
}
publicstaticListasListFromMapKey(Mapmap){
if(map==null||map.size()<1){
returnnull;
}
returnArrayUtil.asListFromSet(map.keySet());
}
publicstaticListasListFromMapValue(Map,T>map){
if(map==null||map.size()<1){
returnnull;
}
Listlist=newArrayList();
Collectionvalues=map.values();
for(Tt:values){
list.add(t);
}
returnlist;
}
@SuppressWarnings("unchecked")
publicstaticT[]fromArray(T...args){
if(args==null||args.length<1){
returnnull;
}
T[]array=(T[])Array.newInstance(args[0].getClass(),args.length);
for(inti=0;iT[]fromList(Listlist){
if(list==null||list.size()<1){
returnnull;
}
Classclz=null;
for(Tt:list){
clz=(Class)t.getClass();
break;
}
T[]array=(T[])Array.newInstance(clz,list.size());
inti=0;
for(Tt:list){
array[i]=t;
i++;
}
returnarray;
}
@SuppressWarnings("unchecked")
publicstaticT[]fromSet(Setset){
if(set==null||set.size()<1){
returnnull;
}
Classclz=null;
for(Tt:set){
clz=(Class)t.getClass();
break;
}
T[]array=(T[])Array.newInstance(clz,set.size());
inti=0;
for(Tt:set){
array[i]=t;
i++;
}
returnarray;
}
publicstaticT[]fromMapKey(Mapmap){
if(map==null||map.size()<1){
returnnull;
}
Setset=map.keySet();
returnArrayUtil.fromSet(set);
}
publicstaticT[]fromMapValue(Map,T>map){
if(map==null||map.size()<1){
returnnull;
}
Listlist=newArrayList();
Collectionvalues=map.values();
for(Tt:values){
list.add(t);
}
returnArrayUtil.fromList(list);
}
@SuppressWarnings("unchecked")
publicstaticSetasSet(T...args){
if(args==null||args.length<1){
returnnull;
}
Setset=newHashSet();
for(inti=0;iSetasSetFromArray(T[]array){
if(array==null||array.length<1){
returnnull;
}
Setset=newHashSet();
for(Tt:array){
set.add(t);
}
returnset;
}
publicstaticSetasSetFromMapKey(Mapmap){
if(map==null||map.size()<1){
returnnull;
}
returnmap.keySet();
}
publicstaticSetasSetFromMapValue(Map,T>map){
if(map==null||map.size()<1){
returnnull;
}
Setset=newHashSet();
Collectionvalues=map.values();
for(Tt:values){
set.add(t);
}
returnset;
}
publicstaticMapasMapFrom(SetkeySet,SetvalueSet){
if(keySet==null||keySet.size()<1||valueSet==null||valueSet.size()<1){
returnnull;
}
Mapmap=newHashMap();
Listlist=ArrayUtil.asListFromSet(valueSet);
inti=0;
for(T1t:keySet){
try{
map.put(t,list.get(i++));
}catch(Exceptione){//超长
map.put(t,null);
}
}
returnmap;
}
@SuppressWarnings("unchecked")
publicstaticStringasString(Stringseparator,T...args){
if(args==null||args.length<1){
returnnull;
}
StringBuildersp=newStringBuilder();
for(inti=0;i
Mapper接口:UserMapper.java
packagecom.sunwii.mybatis.mapper;
importjava.util.List;
importcom.sunwii.mybatis.bean.User;
publicinterfaceUserMapper{
publicUserselectById(intid);
publicListselectByName(Stringname);
publicintinsert(Useruser);
publicintupdate(Useruser);
publicintdelete(intid);
}
映射文件:UserMapper.xml
select*fromt_userwhereid=#{id}
select*fromt_userwherenamelike"%"#{name}"%"
insertinto
t_user(
name,birthday,vip,salary,height,lastlogin,level,state,sex,tels
)values(
#{name},
#{birthday},
#{vip},
#{salary},
#{height},
#{lastlogin},
#{level},
#{state},
#{sex},
#{tels,typeHandler=com.sunwii.mybatis.typehandle.ListTypeHandler}
)
updatet_userset
name=#{name},
birthday=#{birthday},
vip=#{vip},
salary=#{salary},
height=#{height},
lastlogin=#{lastlogin},
level=#{level},
state=#{state},
sex=#{sex},
tels=#{tels,typeHandler=com.sunwii.mybatis.typehandle.ListTypeHandler}
whereid=#{id}
deletefromt_userwhere
id=#{id}
日期工具:CurrentUtil.java
packagecom.sunwii.mybatis.util;
importjava.sql.Timestamp;
importjava.util.Date;
publicclassCurrentUtil{
publicstaticlongcurrentTime(){
returnnewDate().getTime();
}
publicstaticDatecurrentDate(){
returnnewDate();
}
publicstaticjava.sql.DatecurrentSqlDate(){
returnnewjava.sql.Date(currentTime());
}
publicstaticTimestampcurrentTimestamp(){
returnnewjava.sql.Timestamp(currentTime());
}
}
测试示例:
packagecom.sunwii.mybatis.test.mapper;
importjava.util.Arrays;
importjava.util.List;
importorg.apache.commons.logging.Log;
importorg.apache.commons.logging.LogFactory;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.junit.Test;
importcom.sunwii.mybatis.bean.User;
importcom.sunwii.mybatis.enums.Level;
importcom.sunwii.mybatis.enums.Sex;
importcom.sunwii.mybatis.enums.State;
importcom.sunwii.mybatis.mapper.UserMapper;
importcom.sunwii.mybatis.test.insert.TestInsert;
importcom.sunwii.mybatis.util.CurrentUtil;
importcom.sunwii.mybatis.util.SessionFactoryUtil;
publicclasstestMapper{
privatestaticLoglog=LogFactory.getLog(TestInsert.class);
privatestaticSqlSessionFactorysf=SessionFactoryUtil.creat("mybatis-config.xml",true);
@Test
publicvoidtestMapperInsert(){
Useruser=newUser();
//user.setId(50);
user.setName("sunwii");
user.setVip(1);
user.setSalary(3333.00);
user.setHeight(1.70f);
user.setBirthday(CurrentUtil.currentDate());
user.setLastlogin(CurrentUtil.currentTimestamp());
user.setLevel(Level.LEVEL_3);
user.setState(State.OK);
user.setSex(Sex.WOMAN);
user.setTels(Arrays.asList("133xxxxxxx","159xxxxxxxx"));
intrs=0;
SqlSessionsession=sf.openSession();
UserMapperuserMapper=session.getMapper(UserMapper.class);
try{
rs=userMapper.insert(user);
session.commit();
}catch(Exceptione){
rs=0;
session.rollback();
e.printStackTrace();
}finally{
session.close();
}
log.info("操作结果:"+rs);
}
@Test
publicvoidtestMapperUpdate(){
Useruser=newUser();
user.setId(1);
user.setName("sunwii--55550");
user.setVip(1);
user.setSalary(3333.00);
user.setHeight(1.70f);
user.setBirthday(CurrentUtil.currentDate());
user.setLastlogin(CurrentUtil.currentTimestamp());
user.setLevel(Level.LEVEL_2);
user.setState(State.ERROR);
user.setSex(Sex.MAN);
user.setTels(Arrays.asList("136xxxxxx","139xxxxxxx"));
intrs=0;
SqlSessionsession=sf.openSession();
UserMapperuserMapper=session.getMapper(UserMapper.class);
try{
rs=userMapper.update(user);
session.commit();
}catch(Exceptione){
rs=0;
session.rollback();
e.printStackTrace();
}finally{
session.close();
}
log.info("操作结果:"+rs);
}
@Test
publicvoidtestMapperDelete(){
Useruser=newUser(50);
intrs=0;
SqlSessionsession=sf.openSession();
UserMapperuserMapper=session.getMapper(UserMapper.class);
try{
rs=userMapper.delete(user.getId());
session.commit();
}catch(Exceptione){
rs=0;
session.rollback();
e.printStackTrace();
}finally{
session.close();
}
log.info("操作结果:"+rs);
}
@Test
publicvoidtestMapperGetOne(){
Integerid=50;
Useruser=null;
SqlSessionsession=sf.openSession();
UserMapperuserMapper=session.getMapper(UserMapper.class);
user=userMapper.selectById(id);
log.info(user);
}
@Test
publicvoidtestMapperGetList(){
StringuserName="sunwii";
Listusers=null;
SqlSessionsession=sf.openSession();
UserMapperuserMapper=session.getMapper(UserMapper.class);
users=userMapper.selectByName(userName);
for(Useruser:users){
log.info(user);
}
}
}
<>
说明:
这里多余的步骤仅仅是为了存档下代码(以及方便一些初学者不看代码不知道怎么回事的原因:里边涉及了各种常用类型的转换和映射)。
本文中最重要的就是Hibernate的几个包的选取,以及配置文件的精简,还有就是加载Hibernate的SessionFactory的方法。
这些说来说去都是Hibernate的东西。跟Mybatis原本是没有一点关系的。只不过需要用于,那纯属相当于复习一下Hibernate了。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。