注解与反射:
注解就是对代码的注释,反射就是java理解注解的方式。反射可以在类运行时获取类相关属性,方法等。
声明注解:@interface
元注解:@Target @Retention @Document和@Inherited
定义一个注解
/**
* RetentionPolicy:
* SOURCE:在代码中,不会在class中
* CLASS: 编译在class,jvm会忽略
* RUNTTIME: 运行时生效
*/
@Target(ElementType.METHOD) //可以表明注解用在类/方法/字段上
@Retention(RetentionPolicy.RUNTIME) //保留策略
public @interface MyAnno {
//默认的方法,会带到jvm中,会在反射中获得这些值
String value();
}
定义一个反射类
@TableName(value = "类上注解")
public class User {
// @MyAnno(value = "通过反射获取默认值")
@TableField(value = "变量注解")
private String userId;
@MyAnno(value = "通过反射获取方法注解")
private void work(String userId){
System.out.println("");
}
}
获取相关属性
public class ReflecDemo {
public static void main(String[] args) {
TableName tableName = User.class.getAnnotation(TableName.class); //通过反射获取对象
System.out.println(tableName.value());
Field[] declaredFields = User.class.getDeclaredFields(); //获取对象变量
for (Field field : declaredFields) {
TableField tableField = field.getAnnotation(TableField.class);
if(null != tableField){
System.out.println(field.getName() + " - " + tableField.value());
}
}
Method[] declaredMethods = User.class.getDeclaredMethods();
for (Method method : declaredMethods) {
MyAnno myAnno = method.getAnnotation(MyAnno.class);
if(null != myAnno){
System.out.println(method.getName() + " - " + myAnno.value()); //获取方法上注解
}
}
}
}
实现一个ORM框架
目标:通过一个包含自定义注解的POJO类,来描述POJO与数据库中表的对应关系,然后由框架统一完成对数据库中表的CRUD操作。
代码:许宇 (xuyu294636185) - Gitee.com
步骤:
1.定义实体与注解,从实体中解析出CRUD对应的SQL语句
/**
* 定义table注解:指明orderInfo实体对应数据库的那张表
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
public String tableName(); //对应表名
public String orderBy() default ""; //排序字段,可为空
public String order() default ""; //升降序
}
/**
* 表中字段对应关系
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableColumn {
public String dbColumn(); //对应数据库列
public String isPK() default ""; //是否主键
public String dbColumnType() default ""; //数据库字段类型
}
@Table(tableName = "order_info",orderBy = "order_date",order = "desc")
public class OrderInfo {
@TableColumn(dbColumn = "order_id",isPK = "true")
private int orderId;
@TableColumn(dbColumn = "client_name")
private String clientName;
@TableColumn(dbColumn = "produce_name")
private String productName;
@TableColumn(dbColumn = "order_date")
private Date orderDate;
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Date getOrderDate() {
return orderDate;
}
public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
}
/**
* 对OrderInfo对象生成sql语句
*/
public class SQLProvider {
//select xxx,xxx from table where xxx = 'xxx' and xxx = 'xxx' order by xxx desc|asc
public String genQuerySQL(OrderInfo orderInfo) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
StringBuffer sql = new StringBuffer("select ");
StringBuffer paramSql = new StringBuffer();
StringBuffer whereSql = new StringBuffer(" where 1=1 ");
Class<? extends OrderInfo> clazz = orderInfo.getClass();
Table table = clazz.getAnnotation(Table.class);
if (table == null) {
System.out.println("no table");
}
//拿到表名和排序字段和顺序
String tableName = table.tableName();
String order = table.order();
String orderBy = table.orderBy();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (tableColumn != null) {
paramSql.append(tableColumn.dbColumn()).append(",");
}
String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getOrderId();
if(null==fieldValue || StringUtils.isEmpty(field.toString())){
continue;
}
fieldValue = getColumnType(field, fieldValue);
whereSql.append(" and ").append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
}
sql.append(paramSql.substring(0, paramSql.length() - 1)).append(" from ").append(tableName).append(whereSql);
if (!StringUtils.isEmpty(orderBy)) {
sql.append(" order by ").append(orderBy);
if (!StringUtils.isEmpty(order)) {
sql.append(" " + order);
}
}
return sql.toString();
}
//update table set tableColumn = 'xxx',tableColumn = 'xxx' where pk = ?
public String genUpdateSQL(OrderInfo orderInfo) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
StringBuffer sql = new StringBuffer("update ");
StringBuffer setSql = new StringBuffer(" set ");
StringBuffer whereSql = new StringBuffer();
StringBuffer columnSql = new StringBuffer();
Class<? extends OrderInfo> clazz = orderInfo.getClass();
Table table = clazz.getAnnotation(Table.class);
if (null == table) {
System.out.println("未配置表名");
}
String tableName = table.tableName();
//遍历tableColumn属性
for (Field field : clazz.getDeclaredFields()) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (tableColumn == null) {
continue;
}
if (StringUtils.isEmpty(tableColumn.isPK())) {
String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getField();
if (null == fieldValue) {
continue;
}
fieldValue = getColumnType(field, fieldValue);
columnSql.append(tableColumn.dbColumn()).append(" = ").append(fieldValue).append(" , ");
}
}
setSql.append(columnSql.substring(0, columnSql.length() - 2));
for (Field field : clazz.getDeclaredFields()) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
boolean ss = StringUtils.isEmpty(whereSql.toString());
if (!StringUtils.isEmpty(tableColumn.isPK()) && ss) {
String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getOrderId();
if (null == fieldValue || StringUtils.isEmpty(field.toString())) {
continue;
}
fieldValue = getColumnType(field, fieldValue);
whereSql.append(" where ");
whereSql.append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
}
if (StringUtils.isEmpty(whereSql.toString())) {
System.out.println("未设置主键,无法修改");
}
}
sql.append(tableName);
sql.append(setSql);
sql.append(whereSql);
return sql.toString();
}
//delete from table where pk = ?
public String genDeleteSQL(OrderInfo orderInfo) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
StringBuffer sql = new StringBuffer("delete from ");
StringBuffer where = new StringBuffer();
//找到表名
Class<? extends OrderInfo> clazz = orderInfo.getClass(); //获取类对象
Table tableAnno = clazz.getAnnotation(Table.class); //反射获取类属性
String tableName = tableAnno.tableName(); //拿到表名
if (null == tableAnno) {
System.out.println("未配置table注解");
}
//找到列名
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (null == tableColumn) {
continue;
}
if (!StringUtils.isEmpty(tableColumn.isPK()) && StringUtils.isEmpty(where.toString())) {
//通过反射找到get方法获取orderid值
String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getOrderId();
if (null == fieldValue) {
System.out.println("未设置主键,无法删除");
continue;
}
fieldValue = getColumnType(field, fieldValue);
where.append(" WHERE ");
where.append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
}
//没有找到主键
if (StringUtils.isEmpty(where.toString())) {
System.out.println("未设置主键,无法删除");
}
}
//拼接sql
sql.append(tableName).append(where);
return sql.toString();
}
public String genUpdateSQL2(OrderInfo orderInfo) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
StringBuffer sql = new StringBuffer("update ");
StringBuffer setSql = new StringBuffer(" set ");
StringBuffer whereSql = new StringBuffer();
Class<? extends OrderInfo> clazz = orderInfo.getClass();
Table table = clazz.getAnnotation(Table.class);
if (table == null) {
System.out.println("table null");
}
String tableName = table.tableName();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (tableColumn == null) {
continue;
}
//通过反射找到get方法获取orderid值
String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Object fieldValue = clazz.getMethod(getterName).invoke(orderInfo);//相当于orderInfo.getOrderId();
if (null != fieldValue && !StringUtils.isEmpty(fieldValue.toString()) && StringUtils.isEmpty(tableColumn.isPK())) {
setSql.append(tableColumn.dbColumn()).append(" = ").append(fieldValue).append(",");
}
if (!StringUtils.isEmpty(tableColumn.isPK()) && StringUtils.isEmpty(whereSql.toString())) {
if (null == fieldValue) {
System.out.println("pk is null");
}
fieldValue = getColumnType(field, fieldValue);
whereSql.append(" WHERE ");
whereSql.append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
}
}
if (setSql.length() <= 5) {
System.out.println("no column update");
}
if (StringUtils.isEmpty(whereSql.toString())) {
System.out.println("pk is null");
}
sql.append(tableName).append(setSql.substring(0, setSql.length() - 1)).append(whereSql);
return sql.toString();
}
private Object getColumnType(Field field, Object fieldValue) {
//参数类型转换
if (field.getType() == String.class) {
fieldValue = "'" + fieldValue + "'";
} else if (field.getType() == int.class || field.getType() == Integer.class) {
//...各种类型转换
}
return fieldValue;
}
}
public class ReflectTest {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
//解析出orderInfo对应的CRUD操作的sql语句
OrderInfo orderInfo = new OrderInfo();
orderInfo.setOrderId(10001);
orderInfo.setClientName("客户1");
orderInfo.setProductName("商品1");
SQLProvider sqlProvider = new SQLProvider();
System.out.println("增 :" + sqlProvider.genUpdateSQL2(orderInfo));
System.out.println("查 :" + sqlProvider.genQuerySQL(orderInfo));
System.out.println("删 :" + sqlProvider.genDeleteSQL(orderInfo));
}
}
遗留的问题:
①-传入参数是OederInfo,过于具体
②-异常没有处理
③-参数类型处理没有抽象出来
2.封装成通用的Service
/**
* 单例数据库链接
*/
public class DBUtil {
private volatile static Connection connection;
public static Connection getConnection(){
if(null == connection){
synchronized (DBUtil.class){
if(null == connection){
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","root");
}catch (ClassNotFoundException e){
e.printStackTrace();
}catch (SQLException ex){
ex.printStackTrace();
}
}
}
}
return connection;
}
}
/**
* 统一的增删改查
*/
public interface BaseService<T> {
//查
List<T> queryData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException, InstantiationException;
//改
int updateData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException;
//删
int deleteData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException;
}
public class BaseServiceImpl<T> implements BaseService<T> {
private Connection connection = DBUtil.getConnection();
private GenSQLProvider genSQLProvider = new GenSQLProvider();
//查询后结果需要通过反射把值设置进去
public List<T> queryData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException, InstantiationException {
ArrayList<T> result = new ArrayList<T>();
//拿到泛型的类类型,不要new对象获取,太low了,用反射
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
Class<T> repoClazz = (Class<T>)type.getActualTypeArguments()[0];
String sql = genSQLProvider.genQuerySQL(obj);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
//拿到泛型的类类型,不要new对象获取,太low了,用反射
Object instance = repoClazz.newInstance();
Field[] fields = repoClazz.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
String columnKey;
//扩展:没有注解也给映射
Object fieldRes;
if(null!= tableColumn){
columnKey = tableColumn.dbColumn();
}else {
columnKey = field.getName(); //没有则用字段的名字做列
}
try {
fieldRes = resultSet.getObject(columnKey, field.getType());
}catch (SQLException e){
continue;
}
String setterName = "set" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
repoClazz.getMethod(setterName,field.getType()).invoke(instance,fieldRes); //相当于instance.setxxx(fieldRes);
}
result.add((T)instance);
}
return result;
}
public int updateData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException {
String sql = genSQLProvider.genUpdateSQL2(obj);
Statement statement = connection.createStatement();
return statement.executeUpdate(sql);
}
public int deleteData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException {
String sql = genSQLProvider.genDeleteSQL(obj);
Statement statement = connection.createStatement();
return statement.executeUpdate(sql);
}
}
/**
* 对OrderInfo对象生成sql语句
*/
public class GenSQLProvider {
//select xxx,xxx from table where xxx = 'xxx' and xxx = 'xxx' order by xxx desc|asc
public String genQuerySQL(Object obj) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
StringBuffer sql = new StringBuffer("select ");
StringBuffer paramSql = new StringBuffer();
StringBuffer whereSql = new StringBuffer(" where 1=1 ");
Class<?> clazz = obj.getClass();
Table table = clazz.getAnnotation(Table.class);
if (table == null) {
System.out.println("no table");
}
//拿到表名和排序字段和顺序
String tableName = table.tableName();
String order = table.order();
String orderBy = table.orderBy();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (tableColumn != null) {
paramSql.append(tableColumn.dbColumn()).append(",");
}
String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Object fieldValue = clazz.getMethod(getterName).invoke(obj);//相当于orderInfo.getOrderId();
if(null==fieldValue || StringUtils.isEmpty(field.toString())){
continue;
}
fieldValue = getColumnType(field, fieldValue);
whereSql.append(" and ").append(tableColumn.dbColumn()).append(" = ").append(fieldValue);
}
sql.append(paramSql.substring(0, paramSql.length() - 1)).append(" from ").append(tableName).append(whereSql);
if (!StringUtils.isEmpty(orderBy)) {
sql.append(" order by ").append(orderBy);
if (!StringUtils.isEmpty(order)) {
sql.append(" " + order);
}
}
return sql.toString();
}
private Object getColumnType(Field field, Object fieldValue) {
//参数类型转换
if (field.getType() == String.class) {
fieldValue = "'" + fieldValue + "'";
} else if (field.getType() == int.class || field.getType() == Integer.class) {
//...各种类型转换
}
return fieldValue;
}
}
遗留问题:
①异常处理
②数据库链接参数配置项 --整合MyBatis,主要是集成参数类型转换功能。
2.2整合MyBatis
复写Service实现
/**
* 传入的Bean对象
* 不创建对象而使用HasHMap传参是因为会有分页需求,获取版本号之类的
*/
@Component
public class MBBaseServiceImpl<T> implements BaseService<T> {
@Autowired
BaseMapper baseMapper;
//TODO:https://www.bilibili.com/video/BV1hd4y1d788?p=14&spm_id_from=pageDriver&vd_source=85a097599612a3ab01f6d380f0d6b0ef
@Override
public List<T> queryData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException, InstantiationException {
ArrayList<T> result = new ArrayList<>();
//拿到要操作Bean对象的类型,repoClazz代表T的具体类型(OrderInfo.class)
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
Class<?> repoClazz = (Class<?>) type.getActualTypeArguments()[0];
//具体参数的类型
Class<?> objClazz = obj.getClass();
Map<String, Object> paramMap = new HashMap<>();
Field[] fields = objClazz.getDeclaredFields();
for (Field field : fields) {
String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Object fieldValue = obj.getClass().getMethod(getterName).invoke(obj);
if (null != fieldValue) {
paramMap.put(field.getName(), fieldValue);
}
}
List<Map<String, Object>> queryData = baseMapper.selectData(paramMap, repoClazz);
//通过反射来做封装,将Map封装成T实例
for (Map<String, Object> data : queryData) {
Object instance = repoClazz.newInstance();
Field[] fields2 = repoClazz.getDeclaredFields();
for (Field field2 : fields2) {
TableColumn tableColumn = field2.getAnnotation(TableColumn.class);
String columnKey;
Object fieldsRes;
if (null != tableColumn) {
columnKey = tableColumn.dbColumn();
} else {
columnKey = field2.getName();
}
//TODO 要异常处理
fieldsRes = data.get(columnKey);
String setterName = "set" + field2.getName().substring(0, 1) + field2.getName().substring(1);
repoClazz.getMethod(setterName, field2.getType()).invoke(instance, (Integer)fieldsRes);
}
result.add((T) instance);
}
return result;
}
@Override
public int updateData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException {
//拿到要操作Bean对象的类型,repoClazz代表T的具体类型(OrderInfo.class)
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
Class<T> repoClazz = (Class<T>) type.getActualTypeArguments()[0];
//具体参数的类型
Class<?> objClazz = obj.getClass();
Map<String, Object> param = new HashMap<>();
Field[] fields = objClazz.getDeclaredFields();
for (Field field : fields) {
Object fieldValue = ReflectUtil.getValue(obj, field);
if (null != fieldValue) {
param.put(field.getName(), fieldValue);
}
}
return baseMapper.updateData(param, repoClazz);
}
@Override
public int deleteData(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, SQLException {
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
Class<T> repoClazz = (Class<T>) type.getActualTypeArguments()[0];
Class<?> objClazz = obj.getClass();
Map<String, Object> param = new HashMap<>();
Field[] fields = objClazz.getDeclaredFields();
for (Field field : fields) {
Object fieldValue = ReflectUtil.getValue(obj, field);
if (null != fieldValue) {
param.put(field.getName(), fieldValue);
}
}
int i = baseMapper.deleteData(param, repoClazz);
return i;
}
}
public interface BaseMapper {
/**
* @UpdateProvider:动态生成sql,不用在xml中写。type:指定生成的类。method:指定那个方法生成的
* @param param:传入参数
* @param repo:操作对象
* @return
*/
@UpdateProvider(type = MySqlProvider.class, method = "genUpdateSql")
public Integer updateData(@Param("requestData") Map<String, Object> param, @Param("repoClass") Class<?> repo);
@DeleteProvider(type = MySqlProvider.class, method = "genDeleteSql")
public Integer deleteData(@Param("requestData") Map<String, Object> param, @Param("repoClass") Class<?> repo);
@SelectProvider(type = MySqlProvider.class, method = "genSelectSql")
public List<Map<String, Object>> selectData(@Param("requestData") Map<String, Object> param, @Param("repoClass") Class<?> repo);
}
public class MySqlProvider {
public String genUpdateSql(Map<String, Object> param) {
Map<String, Object> paramMap = (Map<String, Object>) param.get("requestData");
Class<?> repoClass = (Class<?>) param.get("repoClass");
Table table = repoClass.getAnnotation(Table.class);
String tableName = table.tableName();
//update table set col1 = #{requestData.attr1},col2=#{requestData.attr2} where orderId = #{request.orderId}
SQL sql = new SQL();
Field[] fields = repoClass.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (null == tableColumn) {
continue;
}
if (paramMap.containsKey(field.getName()) && StringUtils.isEmpty(tableColumn.isPK())) {
sql.SET(tableColumn.dbColumn() + "= #{requestData." + field.getName() + "}");
}
if (!StringUtils.isEmpty(tableColumn.isPK())) {
sql.WHERE(tableColumn.dbColumn() + " = #{requestData." + field.getName() + "}");
continue;
}
}
sql.UPDATE(tableName);
System.out.println(sql.toString());
return sql.toString();
}
public String genDeleteSql(Map<String, Object> param) {
Map<String, Object> paramMap = (Map<String, Object>) param.get("requestData");
Class<?> repoClass = (Class<?>) param.get("repoClass");
Table table = repoClass.getAnnotation(Table.class);
String tableName = table.tableName();
//delete from order_info where orderId = #{requestData.orderId}
SQL sql = new SQL();
Field[] fields = repoClass.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (null == tableColumn) {
continue;
}
if (!StringUtils.isEmpty(tableColumn.isPK())) {
sql.WHERE(tableColumn.dbColumn() + " = #{requestData." + field.getName() + "}");
break;
}
}
sql.DELETE_FROM(tableName);
System.out.println(sql.toString());
return sql.toString();
}
public String genSelectSql(Map<String, Object> param) {
Map<String, Object> paramMap = (Map<String, Object>) param.get("requestData");
Class<?> repoClass = (Class<?>) param.get("repoClass");
Table table = repoClass.getAnnotation(Table.class);
String tableName = table.tableName();
//select ***,*** from order_info where xxx = #{xxx} and xxx = #{xxx} order by xxx desc|asc
SQL sql = new SQL();
Field[] fields = repoClass.getDeclaredFields();
for (Field field : fields) {
TableColumn tableColumn = field.getAnnotation(TableColumn.class);
if (null == tableColumn) {
continue;
}
sql.SELECT(tableColumn.dbColumn());
if (paramMap.containsKey(field.getName())) {
sql.WHERE(tableColumn.dbColumn() + " = #{requestData." + field.getName() + "}");
}
}
sql.FROM(tableName);
if (!StringUtils.isEmpty(table.orderBy())) {
sql.ORDER_BY(table.orderBy());
if (!StringUtils.isEmpty(table.order())) {
//添加排序顺序
}
}
System.out.println(sql.toString());
return sql.toString();
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class AnnoDemoTest {
@Autowired
OrderInfoService orderInfoService;
@Test
public void queryData() throws Exception {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setOrderId(10003);
orderInfo.setClientName("xuyu");
// int i = orderInfoService.deleteData(orderInfo);
// System.out.println(i);
// int j = orderInfoService.updateData(orderInfo);
// System.out.println(j);
List<OrderInfo> orderInfos = orderInfoService.queryData(orderInfo);
for (OrderInfo info : orderInfos) {
System.out.println(info);
}
}
}
3.自动生成
POJO属性类型有要求,必须与JDBC的返回结果一致。实现将采用自动生成的方式来生成POJO对象。
1.怎么拿到数据库的表结构?(通过JDBC连接获取)
/**
* 通过JDBC连接获取数据库表结构
*/
public class JDBCTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.cj.jdbc.Driver");
Properties properties = new Properties();
properties.put("user", "root");
properties.put("password", "root");
properties.put("userInformationSchema", "true"); //加上这个参数就可以从jdbc连接中获取我们想要的结果
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai",
properties);
DatabaseMetaData meta = connection.getMetaData();
System.out.println("==================映射表结构============");
ResultSet tables = meta.getTables("test", "%", "order_info", new String[]{"TABLE"}); //拿到对应的表;参数:库名,全匹配,表名
while (tables.next()) {
ResultSetMetaData metaData = tables.getMetaData();
String table_name = tables.getString("TABLE_NAME"); //拿到表名
String remarks = tables.getString("REMARKS"); //拿到备注
System.out.println("Number for Column:" + metaData.getColumnCount()); //拿到对应列
for (int i = 1; i < metaData.getColumnCount(); i++) {
int metaType = metaData.getColumnType(i);
String metaName = metaData.getColumnName(i);
}
}
System.out.println("==================映射列结构============");
ResultSet columns = meta.getColumns("test", "%", "order_info", "%");//拿到对应列,参数,同上 + 列的全匹配
while (columns.next()) {
String column_name = columns.getString("COLUMN_NAME");//列名
String type_name = columns.getString("TYPE_NAME");//类型
int column_size = columns.getInt("COLUMN_SIZE");//列大小
int decimal_digits = columns.getInt("DECIMAL_DIGITS");//小数点后位数
int nullable = columns.getInt("NULLABLE");//是否为空
String remarks = columns.getString("REMARKS");//注解
System.out.println(column_name + " " + type_name + " " + column_size + " " + decimal_digits + " " + nullable + " " + remarks);
}
System.out.println("==================映射主键信息============");
ResultSet primaryKeys = meta.getPrimaryKeys("test", "%", "order_info");
while (primaryKeys.next()){
ResultSetMetaData metaData = primaryKeys.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i < columnCount; i++) {
System.out.println(metaData.getColumnName(i) + " " + primaryKeys.getString(metaData.getColumnName(i)));
}
}
}
}
2.怎么生成POJO?(①使用StringBuffer拼凑完成的java代码通过流方式实现-MyBatis实现,②freemarker模板引擎)