spring的数据库操作问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring的数据库操作问题相关的知识,希望对你有一定的参考价值。

关于spring的对象映射,我暂时所理解的是,把从数据库查询出来的一行,映射成一个对象。假如在一个一对多的情况下,可以把多行映射成一个对象吗?这个对象拥有一个List类型的属性,list包含多的一方的数据,spring可以这样吗?在不用Hibernate的情况下

spring有自己一套Orm,楼上说得不对,spring 引入jdbc的架包和org.springframework.jdbc-3.1.1.RELEASE.jar配置连接池,就可以连接数据库了,目前数据库是关系型数据库 ORM 主要是把数据库中的关系数据映射称为程序中的对象,spring当然可以了jdbcTemplate就可以实现,或者反射机制+jdbc就可以实现,没有那么复杂,如下代码是我刚刚写的楼主可以直接拿去用

首先构建User模型.应该和数据库字段相对应.数据库结构如下:
User模型:

package com.test.reflection;

public class User
private Integer id;
private String firstname;
private String lastname;
private Integer age;

// 约定的默认构造器(必须)
public User()



@Override
public String toString()
return "id: " + this.id + " firstname: " + this.firstname
+ " lastname: " + this.lastname + " age: " + this.age;


public Integer getId()
return id;


public void setId(Integer id)
this.id = id;


public String getFirstname()
return firstname;


public void setFirstname(String firstname)
this.firstname = firstname;


public String getLastname()
return lastname;


public void setLastname(String lastname)
this.lastname = lastname;


public Integer getAge()
return age;


public void setAge(Integer age)
this.age = age;




然后是上次提供的DBUtils:

package com.test.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public final class DBUtils
private static String url = "jdbc:mysql://localhost:3306/mytest";
private static String user = "root";
private static String password = "root";

// 获得连接
public static Connection getConn() throws SQLException
return DriverManager.getConnection(url, user, password);


// 释放连接
public static void free(ResultSet rs, PreparedStatement ps, Connection conn)
try
if (rs != null)
rs.close();

catch (SQLException e)
e.printStackTrace();
finally
try
if (ps != null)
ps.close();

catch (SQLException e)
e.printStackTrace();
finally

try
if (conn != null)
conn.close();

catch (SQLException e)
e.printStackTrace();








// 加载驱动
static
try
Class.forName("com.mysql.jdbc.Driver");
catch (ClassNotFoundException e)
System.out.println("驱动加载出错");





最后最主要的ORMExample:

package com.test.reflection;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

import com.test.jdbc.DBUtils;

public class ORMExample

public static void main(String[] args)
User user = (User) getObject(
"select id, firstname, lastname, age from users where id = 1",
User.class);
System.out.println(user);



public static <T>T getObject(String sql, Class<T> clazz)
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;

try
conn = DBUtils.getConn();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
// 必须有无参的构造函数
T obj = null;
// 获得共有方法
Method[] ms = clazz.getMethods();
// 通过结果集元数据获得列数
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();

if (rs.next())
obj = clazz.newInstance();
for (int i = 1; i <= columnCount; i++)
String colName = rsmd.getColumnLabel(i);
String methodName = "set"
+ colName.substring(0, 1).toUpperCase()
+ colName.substring(1);
// 循环读取所有方法
for (Method m : ms)
// 列名和set方法名如果相同则调用该方法
if (methodName.equals(m.getName()))
m.invoke(obj, rs.getObject(colName));




return obj;
catch (Exception e)
throw new RuntimeException();
finally
DBUtils.free(rs, ps, conn);


参考技术A spring本身只是提供接口,无法进行数据库连接,这里需要专用的数据库框架去处理,例如Hibernate或者ibatis等,在spring的配置文件里面加入对应的数据库框架的配置以及数据库连接的参数配置就可以进行数据库操作了。
上面你说的多行映射成一个对象的方法Hibernate里面有提供,一般轻量框架都是提供一个数据库操作的平台,直接写对应的sql进行数据库操作,所以无法实现你说的那种映射关系处理。
参考技术B Spring中常用的操作数据库的(Dao)方法
接口:
public interface BaseDAO
void save(T instance);
void update(T instance);
void delete(T instance);
T get(String id);
List<T> findAll();
List<T> findByExample(T instance);
int bulkUpdate(String hql);
int bulkUpdate(String hql, Object value);
int bulkUpdate(String hql, Object[] value);
List<T> find(String queryString);
List<T> find(String queryString, Object obj);
List<T> find(String queryString, Object[] obj);
List<T> findByNamedParam(String queryString, String paramName, Object value);
List<T> findByNamedParam(String queryString, String[] paramNames, Object[] values);
List<T> findByNamedQuery(String queryName);
List<T> findByNamedQuery(String queryName, Object value);
List<T> findByNamedQuery(String queryName, Object[] values);
List<T> findByProperty(String property, Object value);
List<T> findByPagination(final T t, final int firstResult, final int maxResult);
int countByPagination(final T t);

实现类:
import java.sql.*;
import java.util.List;
import org.hibernate.*;
import org.hibernate.criterion.*;
import org.springframework.orm.hibernate3.*;
import org.springframework.orm.hibernate3.support.*;

import com.vo.T;

public abstract class BaseDAOImpl extends HibernateDaoSupport implements BaseDAO

protected abstract Class type(); //反射方法调用类

// 保存
public void save(T instance)
getHibernateTemplate().save(instance);


// 更新
public void update(T instance)
getHibernateTemplate().update(instance);


// 删除
public void delete(T instance)
getHibernateTemplate().delete(instance);


// 根据ID查询
@SuppressWarnings("unchecked")
public T get(String id)
return (T) getHibernateTemplate().get(type(), id);


// 查询所有
@SuppressWarnings("unchecked")
public List<T> findAll()
return getHibernateTemplate().loadAll(type());


// 根据例子查询

@SuppressWarnings("unchecked")
public List<T> findByExample(T instance)
return getHibernateTemplate().findByExample(instance);


// 根据HQL语句进行update操作等
public int bulkUpdate(String hql)
return getHibernateTemplate().bulkUpdate(hql);


// 根据HQL语句进行update操作等
public int bulkUpdate(String hql, Object value)
return getHibernateTemplate().bulkUpdate(hql, value);


// 根据HQL语句进行update操作等
public int bulkUpdate(String hql, Object[] value)
return getHibernateTemplate().bulkUpdate(hql, value);


// 根据HQL语句进行查询
@SuppressWarnings("unchecked")
public List<T> find(String queryString)
return getHibernateTemplate().find(queryString);


// 根据HQL语句进行查询
@SuppressWarnings("unchecked")
public List<T> find(String queryString, Object obj)

return getHibernateTemplate().find(queryString, obj);


// 根据HQL语句进行查询
@SuppressWarnings("unchecked")
public List<T> find(String queryString, Object[] obj)
return getHibernateTemplate().find(queryString, obj);


/**
* 使用命名查询进行查询
*
* @param queryString
* HQL
* @param paramName
* 参数名
* @param value
* 参数值
* @return
*/
@SuppressWarnings("unchecked")
public List<T> findByNamedParam(String queryString, String paramName, Object value)
return this.getHibernateTemplate().findByNamedParam(queryString, paramName, value);


/**
* 使用命名查询进行查询 多个参数
*
* @param queryString
* HQL
* @param paramNames
* 参数名的数组
* @param values
* 参数值的数组
* @return
*/
@SuppressWarnings("unchecked")
public List<T> findByNamedParam(String queryString, String[] paramNames, Object[] values)
return this.getHibernateTemplate().findByNamedParam(queryString, paramNames, values);


/**
* 使用HIBERNATE映射文件中的定义的HQL语句进行查询
*
* @param queryName
* 文件中定义的HQL语句的名字
* @return
*/
@SuppressWarnings("unchecked")
public List<T> findByNamedQuery(String queryName)
return getHibernateTemplate().findByNamedQuery(queryName);


/**
*
* @param queryName
* @param value
* @return
*/
@SuppressWarnings("unchecked")
public List<T> findByNamedQuery(String queryName, Object value)
return getHibernateTemplate().findByNamedQuery(queryName, value);


/**
*
* @param queryName
* @param values
* @return
*/
@SuppressWarnings("unchecked")
public List<T> findByNamedQuery(String queryName, Object[] values)
return getHibernateTemplate().findByNamedQuery(queryName, values);


/**
* 根据属性查询
*
* @param property
* @param value
* @return
*/
@SuppressWarnings("unchecked")
public List<T> findByProperty(String property, Object value)
return this.getHibernateTemplate().findByCriteria(
DetachedCriteria.forClass(type()).add(Restrictions.eq(property, value)));


/**
* 分页查询
* 注:不能满足要求子类重写该方法
* @param t
* @param firstResult
* @param maxResult
* @return 返回分页查询的数据
*/
@SuppressWarnings("unchecked")
public List<T> findByPagination(final T t, final int firstResult, final int maxResult)
return getHibernateTemplate().executeFind(new HibernateCallback()
public Object doInHibernate(Session session) throws HibernateException, SQLException
Criteria criteria = session.createCriteria(type());
criteria.add(Example.create(t).enableLike(MatchMode.ANYWHERE));
criteria.setFirstResult(firstResult);
criteria.setMaxResults(maxResult);
return criteria.list();

);


/**
* 分页统计查询
*
* @param t
* @return 一共有多少条数据
*/
@SuppressWarnings("unchecked")
public int countByPagination(final T t)
return (Integer) getHibernateTemplate().execute(new HibernateCallback()
public Object doInHibernate(Session session) throws HibernateException, SQLException
Criteria criteria = session.createCriteria(type());
criteria.setProjection(Projections.rowCount());
criteria.add(Example.create(t).enableLike(MatchMode.ANYWHERE));
return criteria.uniqueResult();

);



反射类:

public class ClassInfoDAO

@SuppressWarnings("unchecked")
protected Class type()
return User.class;


来自 AsyncUncaughtExceptionHandler(spring) 的休眠数据库操作

【中文标题】来自 AsyncUncaughtExceptionHandler(spring) 的休眠数据库操作【英文标题】:hibernate db operation from AsyncUncaughtExceptionHandler(spring) 【发布时间】:2018-12-28 03:59:57 【问题描述】:

当我尝试使用 Hibernate 从 AsyncUncaughtExceptionHandler 执行数据库操作时遇到以下问题(如果@Async 方法中有任何异常将被触发)。

代码片段:

CustomAsyncUncaughtExceptionHandler :

public class CustomAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler 

private final Log logger = LogFactory.getLog(CustomAsyncUncaughtExceptionHandler.class);

@Autowired
private AuditService auditService;

@Override
public void handleUncaughtException(final Throwable ex, final Method method, final Object... params) 

    if (params[0] instanceof HttpServletRequest) 
        final HttpServletRequest request = (HttpServletRequest) params[0];
        this.auditService.auditAsyncException(ex.getMessage(), ex instanceof Exception
                ? (Exception) ex
                : null, request.getRemoteUser(), request.getRequestURI(), this.getMapOfParameters(request));
    
    else 
        this.logger.error(String.format("Unexpected error occurred invoking async " + "method '%s'.", method), ex);
    



auditAsyncException:

@Service
public class AuditServiceImpl implements AuditService 
private static final Logger LOG = 
LoggerFactory.getLogger(AuditServiceImpl.class);
@Autowired
private AuditDao auditDao;

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public ExceptionAudit auditAsyncException(final String message, final Exception ex, final String userid,
        final String requestUri, final Map<String, String> parameters) 

    LOG.debug("auditException");

    ExceptionSeverity severtiy = ExceptionSeverity.HIGH;

    final ExceptionAudit exceptionAudit =
            new ExceptionAudit(message, ex, userid, requestUri, severtiy, parameters, null);

    this.auditDao.saveAuditException(exceptionAudit);

    LOG.error(message, ex);
    return exceptionAudit;


错误信息:

ERROR [executor-1] o.s.s.a.AnnotationAsyncExecutionInterceptor.handleError(AsyncExecutionAspectSupport.java:300)| Exception handler for 
async method 'public sendSMSOrScheduleDelivery(javax.servlet.http.HttpServletRequest,java.lang.Long,java.lang.String,java.lang.Long,java.util.List<java.lang.String>,java.lang.String)' threw unexpected exception itself
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:133) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:688) ~[hibernate-core-5.1.2.Final.jar:5.1.2.Final]
at .GeneralDaoImpl.getSession(GeneralDaoImpl.java:48) ~[classes/:na]
at .AuditDaoImpl.saveAuditException(AuditDaoImpl.java:43) ~[classes/:na]
at AuditServiceImpl.auditAsyncException(AuditServiceImpl.java:187) ~[classes/:na]
at CustomAsyncUncaughtExceptionHandler.handleUncaughtException(CustomAsyncUncaughtExceptionHandler.java:38) ~[classes/:na]
at org.springframework.aop.interceptor.AsyncExecutionAspectSupport.handleError(AsyncExecutionAspectSupport.java:297) ~[spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:124) [spring-aop-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at controller.MappedDiagnosticContextThreadPoolTaskExecutor$1.call(MappedDiagnosticContextThreadPoolTaskExecutor.java:111) [classes/:na]
at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_80]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_80]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_80]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_80]

任何指针?

【问题讨论】:

Caused by 不在您发布的日志中。添加它会很有帮助。 【参考方案1】:

我建议按照我的实现。

https://github.com/IronJhon/system_bibliotec/blob/master/src/main/java/com/system/bibliotec/config/CustomAsyncExceptionHandler.java

https://github.com/IronJhon/system_bibliotec/blob/master/src/main/java/com/system/bibliotec/config/async/ExceptionHandlingAsyncTaskExecutor.java

https://github.com/IronJhon/system_bibliotec/blob/master/src/main/java/com/system/bibliotec/config/AsyncConfigurationBibliotecSystem.java

在 AsyncUncaughtExceptionHandler 的上下文中,无法连接到 spring 管理的 beans/服务。我不知道...

字体:Custom AsyncUncaughtExceptionHandler

【讨论】:

以上是关于spring的数据库操作问题的主要内容,如果未能解决你的问题,请参考以下文章

spring 14-Spring框架JDBC操作

使用 Spring JdbcTemplate 进行多个数据库操作

一文搞懂 Spring 数据库事务操作!

Spring 嵌套事务提交时机对其他查询操作的影响分析

Spring 嵌套事务提交时机对其他查询操作的影响分析

如何在 Spring 中将数据插入到可操作的脚本中