package cn.xnatural.jpa;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.query.Query;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 对应一个数据源
*/
public class Repo implements AutoCloseable {
protected static final Logger log = LoggerFactory.getLogger(Repo.class);
/**
* 属性集: 包含 datasource, hibernate 两部分
*/
protected final Map<String, Object> attrs;
/**
* {@link SessionFactory}
*/
protected SessionFactory sf;
/**
* 当前数据源
*/
protected DataSource datasource;
/**
* 关联哪些实体
*/
protected final List<Class<?>> annotatedClass = new LinkedList<>();
public Repo() { this((Map<String, Object>) null); }
/**
* 连接url
* @param jdbcUrl jdbc url
*/
public Repo(String jdbcUrl) {
this(Stream.of(Collections.singletonMap("jdbcUrl", jdbcUrl))
.collect(Collectors.toConcurrentMap(m -> m.keySet().iterator().next(), m -> m.values().iterator().next())));
}
/**
* 指定jdbcUrl创建Repo
* @param jdbcUrl jdbc连接串
* @param username 用户名
* @param password 密码
* @param minIdle 最小空闲连接
* @param maxActive 最大活动连接
*/
public Repo(String jdbcUrl, String username, String password, Integer minIdle, Integer maxActive) {
this(Stream.of(Collections.singletonMap("jdbcUrl", jdbcUrl),
Collections.singletonMap("minimumIdle", minIdle), Collections.singletonMap("maximumPoolSize", maxActive),
Collections.singletonMap("username", username), Collections.singletonMap("password", password)
).collect(Collectors.toConcurrentMap(m -> m.keySet().iterator().next(), m -> m.values().iterator().next())));
}
/**
* {@link #Repo(String, String, String, Integer, Integer)}
* @param jdbcUrl jdbc连接串
* @param username 用户名
* @param password 密码
*/
public Repo(String jdbcUrl, String username, String password) { this(jdbcUrl, username, password, 1, 8); }
/**
* 根据属性集创建Repo
* @param attrs 属性集
*/
public Repo(Map<String, Object> attrs) {
this.attrs = attrs == null ? new ConcurrentHashMap<>() : attrs;
}
/**
* 初始化
* @return 当前 {@link Repo}
*/
public Repo init() {
if (sf != null) throw new RuntimeException("Already inited");
//1. 数据源
if (datasource != null) throw new RuntimeException("DataSource already exist");
datasource = createDataSource(attrs);
sf = createSessionFactory(attrs, datasource, annotatedClass);
return this;
}
/**
* 关闭Repo
*/
@Override
public void close() {
try {
sf.close(); sf = null;
datasource.getClass().getMethod("close").invoke(datasource);
datasource = null;
} catch (Exception e) {}
}
/**
* 设置 属性
* @param key 属性key
* @param value 属性值
* @return {@link Repo}
*/
public Repo setAttr(String key, Object value) { attrs.put(key, value); return this; }
/**
* 获取属性
* @param key 属性key
* @return 属性值
*/
public Object getAttr(String key) { return attrs.get(key); }
/**
* 添加被管理的实体类
* @param clzs 实体类
* @return 当前 {@link Repo}
*/
public Repo entities(Class<?>... clzs) {
if (sf != null) throw new RuntimeException("Already inited");
if (clzs == null) return this;
for (Class<?> clz : clzs) {
if (annotatedClass.stream().noneMatch(c -> c.equals(clz))) {
annotatedClass.add(clz);
}
}
return this;
}
// 事务的线程标记
protected static final ThreadLocal<Boolean> txFlag = ThreadLocal.withInitial(() -> false);
/**
* 事务执行方法
* @param fn 数据库操作函数
* @param okFn 执行成功后回调
* @param failFn 执行失败后回调
*/
public <T> T trans(Function<Session, T> fn, Runnable okFn, Consumer<Throwable> failFn) {
if (sf == null) throw new RuntimeException("Please init first");
Session session = sf.getCurrentSession();
// 当前线程存在事务
if (txFlag.get()) return fn.apply(session);
else { // 当前线程没有事务,开启新事务
Transaction tx = session.getTransaction();
tx.begin(); txFlag.set(true);
Throwable ex = null;
try {
T r = fn.apply(session); tx.commit(); txFlag.set(false); session.close();
return r;
} catch (Throwable t) {
tx.rollback(); txFlag.set(false); ex = t; session.close();
if (failFn == null) throw t;
} finally {
if (ex != null) {
if (failFn != null) failFn.accept(ex);
} else {// 成功
if (okFn != null) okFn.run();
}
}
}
return null;
}
/**
* {@link #trans(Function, Runnable, Consumer)}
* @param fn 数据库操作函数. 事务
*/
public <T> T trans(Function<Session, T> fn) { return trans(fn, null, null); }
/**
* 在session中处理
* @param fn 会话操作函数
*/
public <T> T doSession(Function<Session, T> fn) {
if (txFlag.get()) return fn.apply(sf.getCurrentSession());
else {
try (Session se = sf.openSession()) {
return fn.apply(se);
}
}
}
/**
* 根据实体类, 查表名字
* @param eType 实体Class
* @return 表名
*/
public <E extends IEntity> String tbName(Class<E> eType) {
if (sf == null) throw new RuntimeException("Please init first");
return ((AbstractEntityPersister) ((MappingMetamodel) sf.getMetamodel()).locateEntityDescriptor(eType)).getRootTableName().replace("`", "");
}
/**
* 连接mysql当前数据库的库名
* @return 数据库名
*/
public String getDbName() {
if (sf == null) throw new RuntimeException("Please init first");
return ((SessionFactoryImpl) sf).getJdbcServices().getJdbcEnvironment().getCurrentCatalog().getText();
}
/**
* 连接的数据库Dialect
* @return Dialect
*/
public Dialect getDialect() {
if (sf == null) throw new RuntimeException("Please init first");
return ((SessionFactoryImpl) sf).getJdbcServices().getD
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
xjpa-master.zip (32个子文件)
xjpa-master
pom.xml 8KB
src
test
main
resources
logback.xml 1KB
java
JpaTest.java 15KB
entity
Db.java 799B
TestUUIDEntity.java 334B
TestNanoIDEntity.java 852B
CusIdEntity.java 339B
Test.java 671B
User.java 933B
main
java
cn
xnatural
jpa
EUpdater.java 114B
Repo.java 37KB
SnowFlakeIdGenerator.java 4KB
OpHistory.java 2KB
EDeleting.java 157B
PhysicalNaming.java 3KB
CriteriaSpec.java 570B
NanoIDEntity.java 677B
UUIDGenerator.java 570B
BaseEntity.java 850B
EVersioning.java 330B
Page.java 3KB
ECreatable.java 278B
EUpdatable.java 223B
LongIdEntity.java 507B
ImplicitNaming.java 593B
UUIDEntity.java 664B
IEntity.java 195B
SnowFlakeIdEntity.java 674B
ECreator.java 114B
NanoIDGenerator.java 2KB
LICENSE 11KB
.gitignore 89B
共 32 条
- 1
资源评论
Java程序员-张凯
- 粉丝: 1w+
- 资源: 6742
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功