通用的增删改查
1. 利用xml配置实体类和数据库表名的映射关系2. 根据xml设计,用正确的数据结构映射类封装好xml信息3. 得到数据库连接前,读取xml信息,用map封装成映射数据4. 写dao时根据反射和map生成sql语句,拿到属性值测试
为了解决上一篇文中实体类的局限性:不可加字段;实体名,表名,列的字段一样,而且顺序一样上一篇反射实现dao层增删改查 本文实现结构
1. 利用xml配置实体类和数据库表名的映射关系
sql语句
create table ticket_info
(
ticket_id number
primary key,
ticket_name
varchar(30) not null,
ticket_price number
(10, 2) not null
)
create sequence ticket_seq
create table goods_info
(
goods_id number
primary key,
goods_name
varchar(30) not null,
goods_price number
(10, 2) not null,
goods_date
date not null,
goods_factory
varchar(50) not null
)
create sequence goods_seq
xml, 映射表属性和实体类列
goods.xml
<?xml version
="1.0" encoding
="UTF-8"?
>
<class name
="com.lovely.entity.Goods" table="goods_info">
<id name
="gid" column="goods_id">
<sequence
>goods_seq
</sequence
>
</id
>
<property name
="gname" column="goods_name"></property
>
<property name
="gprice" column="goods_price"></property
>
<property name
="gdate" column="goods_date"></property
>
<property name
="gfactory" column="goods_factory"></property
>
</class
>
ticket.xml
<?xml version
="1.0" encoding
="UTF-8"?
>
<!
<class name
="com.lovely.entity.Ticket" table="ticket_info"> <!
<id name
="tid" column="ticket_id"> <!
<sequence
>ticket_seq
</sequence
>
</id
>
<property name
="tname" column="ticket_name"></property
> <!
<property name
="tprice" column="ticket_price"></property
>
</class
>
goods, 和 entity的实体类
package com
.lovely
.entity
;
import java
.sql
.Date
;
public class Goods {
private Integer gid
;
private String gname
;
private Double gprice
;
private Date gdate
;
private String gfactory
;
public Goods() {}
public Integer
getGid() {
return gid
;
}
public void setGid(Integer gid
) {
this.gid
= gid
;
}
public String
getGname() {
return gname
;
}
public void setGname(String gname
) {
this.gname
= gname
;
}
public Double
getGprice() {
return gprice
;
}
public void setGprice(Double gprice
) {
this.gprice
= gprice
;
}
public Date
getGdate() {
return gdate
;
}
public void setGdate(Date gdate
) {
this.gdate
= gdate
;
}
public String
getGfactory() {
return gfactory
;
}
public void setGfactory(String gfactory
) {
this.gfactory
= gfactory
;
}
}
package com
.lovely
.entity
;
public class Ticket {
private
Integer tid
;
private String tname
;
private
Double tprice
;
public Ticket
() {}
public Ticket
(Integer tid
, String tname
, Double tprice
) {
super
();
this
.tid
= tid
;
this
.tname
= tname
;
this
.tprice
= tprice
;
}
public Integer getTid
() {
return tid
;
}
public void setTid
(Integer tid
) {
this
.tid
= tid
;
}
public String getTname
() {
return tname
;
}
public void setTname
(String tname
) {
this
.tname
= tname
;
}
public Double getTprice
() {
return tprice
;
}
public void setTprice
(Double tprice
) {
this
.tprice
= tprice
;
}
@Override
public String toString
() {
return "Ticket [tid=" + tid
+ ", tname=" + tname
+ ", tprice=" + tprice
+ "]\n";
}
}
2. 根据xml设计,用正确的数据结构映射类封装好xml信息
主键id
package com
.lovely
.base
;
public class MapperId {
private String idName
;
private String idColumn
;
private String seqName
;
public String
getIdName() {
return idName
;
}
public void setIdName(String idName
) {
this.idName
= idName
;
}
public String
getIdColumn() {
return idColumn
;
}
public void setIdColumn(String idColumn
) {
this.idColumn
= idColumn
;
}
public String
getSeqName() {
return seqName
;
}
public void setSeqName(String seqName
) {
this.seqName
= seqName
;
}
@Override
public String
toString() {
return "MapperId [idName=" + idName
+ ", idColumn=" + idColumn
+ ", seqName=" + seqName
+ "]";
}
}
MapperData 映射数据类
package com
.lovely
.base
;
import java
.util
.LinkedHashMap
;
public class MapperData {
private String className
;
private String tableName
;
private MapperId mapperId
;
private LinkedHashMap
<String, String> properties
= new LinkedHashMap<String, String>();
public String
getClassName() {
return className
;
}
public void setClassName(String className
) {
this.className
= className
;
}
public String
getTableName() {
return tableName
;
}
public void setTableName(String tableName
) {
this.tableName
= tableName
;
}
public MapperId
getMapperId() {
return mapperId
;
}
public void setMapperId(MapperId mapperId
) {
this.mapperId
= mapperId
;
}
public LinkedHashMap
<String, String> getProperties() {
return properties
;
}
public void setProperties(LinkedHashMap
<String, String> properties
) {
this.properties
= properties
;
}
@Override
public String
toString() {
return "MapperData [className=" + className
+ ", tableName="
+ tableName
+ ", mapperId=" + mapperId
+ ", properties="
+ properties
+ "]\n";
}
}
3. 得到数据库连接前,读取xml信息,用map封装成映射数据
实体属性名和表的列名一样,也封装在map里面了
package com
.lovely
.dao
;
import java
.io
.File
;
import java
.lang
.reflect
.Field
;
import java
.net
.URL
;
import java
.sql
.Connection
;
import java
.sql
.DriverManager
;
import java
.sql
.PreparedStatement
;
import java
.sql
.ResultSet
;
import java
.sql
.SQLException
;
import java
.util
.HashMap
;
import java
.util
.LinkedHashMap
;
import java
.util
.List
;
import org
.dom4j
.Document
;
import org
.dom4j
.Element
;
import org
.dom4j
.io
.SAXReader
;
import com
.lovely
.base
.MapperData
;
import com
.lovely
.base
.MapperId
;
public class BaseDao {
static {
try {
Class
.forName("oracle.jdbc.OracleDriver");
} catch (ClassNotFoundException e
) {
e
.printStackTrace();
}
}
public static HashMap
<String, MapperData> map
= new HashMap<String, MapperData>();
static {
try {
Class
<?> baseDaoClass
= Class
.forName("com.lovely.dao.BaseDao");
URL url
= baseDaoClass
.getResource("/com/lovely/mapper");
String path
= url
.getFile();
File file
= new File(path
);
File
[] files
= file
.listFiles();
for (int i
= 0; i
< files
.length
; i
++) {
SAXReader reader
= new SAXReader();
Document doc
= reader
.read(files
[i
]);
Element root
= doc
.getRootElement();
MapperData mapperData
= new MapperData();
mapperData
.setClassName(root
.attributeValue("name"));
mapperData
.setTableName(root
.attributeValue("table"));
MapperId mapperId
= new MapperId();
Element primaryKey
= root
.element("id");
mapperId
.setIdName(primaryKey
.attributeValue("name"));
mapperId
.setIdColumn(primaryKey
.attributeValue("column"));
mapperId
.setSeqName(primaryKey
.elementText("sequence"));
mapperData
.setMapperId(mapperId
);
@SuppressWarnings("unchecked")
List
<Element> property
= root
.elements("property");
LinkedHashMap
<String, String> lhm
= new LinkedHashMap<String, String>();
for (Element field
: property
) {
lhm
.put(field
.attributeValue("name"), field
.attributeValue("column"));
}
mapperData
.setProperties(lhm
);
map
.put(root
.attributeValue("name"), mapperData
);
}
} catch (Exception e
) {
e
.printStackTrace();
}
}
static {
try {
Class
<?> c
= BaseDao
.class;
String path
= c
.getResource("/com/lovely/entity").getFile();
File file
= new File(path
);
File
[] files
= file
.listFiles();
for (int i
= 0; i
< files
.length
; i
++) {
String fileName
= files
[i
].getName();
String className
= "com.lovely.entity." + fileName
.substring(0, fileName
.indexOf("."));
if (!map
.containsKey(className
)) {
Class
<?> cc
= Class
.forName(className
);
MapperData value
= new MapperData();
value
.setClassName(cc
.getName());
value
.setTableName(cc
.getSimpleName());
Field
[] fields
= cc
.getDeclaredFields();
Field
.setAccessible(fields
, true);
String primaryKeyName
= fields
[0].getName();
MapperId mapperId
= new MapperId();
mapperId
.setIdName(primaryKeyName
);
mapperId
.setIdColumn(primaryKeyName
);
mapperId
.setSeqName("seq_" + cc
.getSimpleName());
value
.setMapperId(mapperId
);
LinkedHashMap
<String, String> properties
= new LinkedHashMap<String, String>();
for (int j
= 1; j
< fields
.length
; j
++) {
properties
.put(fields
[j
].getName(), fields
[j
].getName());
}
value
.setProperties(properties
);
map
.put(className
, value
);
}
}
} catch(Exception e
) {
e
.printStackTrace();
}
}
public static void main(String
[] args
) {
System
.out
.println(map
);
}
public static Connection
getConn() {
Connection conn
= null
;
String url
= "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
try {
conn
= DriverManager
.getConnection(url
, "scott", "scott");
} catch (SQLException e
) {
e
.printStackTrace();
}
return conn
;
}
public static void closeAll(Connection conn
, PreparedStatement ps
, ResultSet rs
) {
try {
if (rs
!= null
)
rs
.close();
if (ps
!= null
)
ps
.close();
if (conn
!= null
)
conn
.close();
} catch (SQLException e
) {
e
.printStackTrace();
}
}
}
4. 写dao时根据反射和map生成sql语句,拿到属性值
curd实现
package com
.lovely
.dao
;
import java
.lang
.reflect
.Field
;
import java
.sql
.*
;
import java
.util
.ArrayList
;
import java
.util
.Collection
;
import java
.util
.LinkedHashMap
;
import java
.util
.List
;
import java
.util
.Map
.Entry
;
import java
.util
.Set
;
import com
.lovely
.base
.MapperData
;
import com
.lovely
.base
.MapperId
;
public class CommonDao {
public int save(Object entity
) {
int count
= -1;
Class
<?> c
= entity
.getClass();
MapperData mapperData
= BaseDao
.map
.get(c
.getName());
StringBuffer sql
= new StringBuffer();
sql
.append("insert into ");
sql
.append(mapperData
.getTableName() + " values (");
sql
.append(mapperData
.getMapperId().getSeqName() + ".nextval");
LinkedHashMap
<String,String> properties
= mapperData
.getProperties();
Set
<String> keySet
= properties
.keySet();
for (int i
= 0; i
< keySet
.size(); i
++) {
sql
.append(", ?");
}
sql
.append(")");
System
.out
.println(sql
);
Connection conn
= BaseDao
.getConn();
PreparedStatement ps
= null
;
try {
ps
= conn
.prepareStatement(sql
.toString());
int index
= 1;
for (String entityColumn
: keySet
) {
Field field
= c
.getDeclaredField(entityColumn
);
field
.setAccessible(true);
ps
.setObject(index
, field
.get(entity
));
index
++;
}
count
= ps
.executeUpdate();
} catch (Exception e
) {
e
.printStackTrace();
} finally {
BaseDao
.closeAll(conn
, ps
, null
);
}
return count
;
}
public List
<Object> queryAll(Class
<?> c
) {
List
<Object> list
= new ArrayList<Object>();
MapperData mapperData
= BaseDao
.map
.get(c
.getName());
String sql
= "select * from " + mapperData
.getTableName();
Connection conn
= BaseDao
.getConn();
PreparedStatement ps
= null
;
ResultSet rs
= null
;
LinkedHashMap
<String, String> properties
= mapperData
.getProperties();
try {
ps
= conn
.prepareStatement(sql
);
rs
= ps
.executeQuery();
String primaryKeyName
= mapperData
.getMapperId().getIdColumn();
String idName
= mapperData
.getMapperId().getIdName();
while (rs
.next()) {
Object entity
= c
.newInstance();
Object primaryKeyValue
= rs
.getObject(primaryKeyName
);
Field primaryFiled
= c
.getDeclaredField(idName
);
if (primaryFiled
.getType() == Integer
.class)
primaryKeyValue
= rs
.getInt(primaryKeyName
);
primaryFiled
.setAccessible(true);
primaryFiled
.set(entity
, primaryKeyValue
);
Set
<Entry
<String,String>> entrySet
= properties
.entrySet();
for (Entry
<String, String> entry
: entrySet
) {
String filedName
= entry
.getKey();
String columnName
= entry
.getValue();
Object attributValue
= rs
.getObject(columnName
);
Field f
= c
.getDeclaredField(filedName
);
if (f
.getType() == Double
.class) {
attributValue
= rs
.getDouble(columnName
);
} else if (f
.getType() == java
.sql
.Timestamp
.class) {
attributValue
= rs
.getTimestamp(columnName
);
}
f
.setAccessible(true);
f
.set(entity
, attributValue
);
}
list
.add(entity
);
}
} catch (Exception e
) {
e
.printStackTrace();
} finally {
BaseDao
.closeAll(conn
, ps
, rs
);
}
return list
;
}
public Object
queryOne(Object obj
) {
Object entity
= null
;
Class
<?> c
= obj
.getClass();
MapperData mapperData
= BaseDao
.map
.get(c
.getName());
String sql
= "select * from " + mapperData
.getTableName() + " where " + mapperData
.getMapperId().getIdColumn() + " = ?";
System
.out
.println(sql
);
Connection conn
= BaseDao
.getConn();
PreparedStatement ps
= null
;
ResultSet rs
= null
;
try {
MapperId mapperId
= mapperData
.getMapperId();
ps
= conn
.prepareStatement(sql
);
Field field
= c
.getDeclaredField(mapperId
.getIdName());
field
.setAccessible(true);
ps
.setObject(1, field
.get(obj
));
rs
= ps
.executeQuery();
LinkedHashMap
<String,String> properties
= mapperData
.getProperties();
Set
<Entry
<String, String>> entrySet
= properties
.entrySet();
if (rs
.next()) {
entity
= c
.newInstance();
Field idFiled
= c
.getDeclaredField(mapperId
.getIdName());
idFiled
.setAccessible(true);
Object idColumn
= rs
.getObject(mapperId
.getIdColumn());
System
.out
.println(idColumn
+ "\t" + mapperId
.getIdName() + "\t" + mapperId
.getIdColumn());
if (idFiled
.getType() == Integer
.class) {
idColumn
= rs
.getInt(mapperId
.getIdColumn());
}
idFiled
.set(entity
, idColumn
);
for (Entry
<String, String> entry
: entrySet
) {
Field f1
= c
.getDeclaredField(entry
.getKey());
f1
.setAccessible(true);
Object value
= rs
.getObject(entry
.getValue());
if (f1
.getType() == Double
.class)
value
= rs
.getDouble(entry
.getValue());
else if (f1
.getType() == Timestamp
.class) {
value
= rs
.getTimestamp(entry
.getValue());
}
f1
.set(entity
, value
);
}
}
} catch (Exception e
) {
e
.printStackTrace();
} finally {
BaseDao
.closeAll(conn
, ps
, rs
);
}
return entity
;
}
public int update(Object entity
) {
int count
= -1;
Class
<?> c
= entity
.getClass();
StringBuffer sql
= new StringBuffer();
MapperData mapperData
= BaseDao
.map
.get(c
.getName());
sql
.append("update " + mapperData
.getTableName() + " set ");
LinkedHashMap
<String,String> properties
= mapperData
.getProperties();
Set
<String> keySet
= properties
.keySet();
Collection
<String> cloumnNames
= properties
.values();
int cloumnSize
= cloumnNames
.size();
int index
= 0;
for (String cloumnName
: cloumnNames
) {
if (index
< cloumnSize
- 1)
sql
.append(cloumnName
+ " = ?, ");
else
sql
.append(cloumnName
+ " = ?");
index
++;
}
sql
.append(" where " + mapperData
.getMapperId().getIdColumn() + " = ?");
System
.out
.println(sql
);
Connection conn
= BaseDao
.getConn();
PreparedStatement ps
= null
;
try {
ps
= conn
.prepareStatement(sql
.toString());
int paramIndex
= 1;
for (String fieldAttribute
: keySet
) {
Field field
= c
.getDeclaredField(fieldAttribute
);
field
.setAccessible(true);
Object obj
= field
.get(entity
);
ps
.setObject(paramIndex
, obj
);
paramIndex
++;
}
Field field
= c
.getDeclaredField(mapperData
.getMapperId().getIdName());
field
.setAccessible(true);
ps
.setObject(paramIndex
, field
.get(entity
));
count
= ps
.executeUpdate();
} catch (Exception e
) {
e
.printStackTrace();
} finally {
BaseDao
.closeAll(conn
, ps
, null
);
}
return count
;
}
public int delete(Object obj
) {
int count
= -1;
Class
<?> c
= obj
.getClass();
MapperData mapperData
= BaseDao
.map
.get(c
.getName());
MapperId mapperId
= mapperData
.getMapperId();
String sql
= "delete from " + mapperData
.getTableName() + " where " + mapperId
.getIdColumn() + " = ?";
Connection conn
= BaseDao
.getConn();
PreparedStatement ps
= null
;
try {
ps
= conn
.prepareStatement(sql
);
Field field
= c
.getDeclaredField(mapperId
.getIdName());
field
.setAccessible(true);
ps
.setObject(1, field
.get(obj
));
count
= ps
.executeUpdate();
} catch (Exception e
) {
e
.printStackTrace();
} finally {
BaseDao
.closeAll(conn
, ps
, null
);
}
return count
;
}
}
测试
一句代码搞定查询。。。
package com
.lovely
.test
;
import com
.lovely
.dao
.CommonDao
;
import com
.lovely
.entity
.Student
;
import com
.lovely
.entity
.Ticket
;
public class Test1 {
public static void main(String
[] args
) {
CommonDao dao
= new CommonDao();
System
.out
.println(dao
.queryAll(Studdent
.getClass()));
System
.out
.println(dao
.queryAll(Ticket
.class));
}
}
[Student
[sid
=46, sname
=jack
, sgender
=male
, sbirth
=2020-07-02 20:24:01.0, saddress
=null
, sinfo
=null
]
]
[Ticket
[tid
=2, tname
=花木兰
, tprice
=33.2]
, Ticket
[tid
=3, tname
=阿凡达
2, tprice
=50.5]
]