2024年最全java开发之Java ORM 框架推荐,java校招面试题多线程

总结

在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了

面试真题

Spring源码笔记

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

Member.queryByPrimaryKey(1, Member.HAS_MANY_ORDERS);

Member.queryByName(“braisdom”, Member.HAS_MANY_ORDERS);

复制代码

上述代码中的 Member.HAS_MANY_ORDERS 属性为ObjectiveSQL 自动生成,在特殊情况下,可以基于 com.github.braisdom.objsql.relation.Relationship 自定义关联关系的构建逻辑。

4.7 分页查询

// Create a Page instance with current page and page size

Page page = Page.create(0, 10);

PagedList members = Member.pagedQueryAll(page, Member.HAS_MANY_ORDERS);

PagedList members = Member.pagedQuery(page, “name = ?”, “braisdom”);

复制代码

4.8 Query 接口编程

Query query = Member.createQuery();

query.project(“name”).groupBy(“name”).having(“COUNT(*) > 0”).orderBy(“name DESC”);

List members = query.execute(Member.HAS_MANY_ORDERS);

// Paged querying with querying dynamically

Paginator paginator = Databases.getPaginator();

Page page = Page.create(0, 10);

PagedList pagedMembers = paginator

.paginate(page, query, Member.class, Member.HAS_MANY_ORDERS);

复制代码

针对SQL 中的分组和排序,需要通过Query 接口完成,同时Query 接口也可以进行分页和关联对象查询。

4.9 Validation

ObjectiveSQL Validation 内部集成了Jakarta Bean Validation

详细使用方法请参考:beanvalidation.org/

4.9.1 手工调用 validate 方法

Member newMember = new Member()

.setNo(“100”)

.setName(“Pamela”)

.setGender(1)

.setMobile(“15011112222”);

// Violations occurred in field ‘no’

Validator.Violation[] violations = newMember.validate();

复制代码

4.9.2 创建对象时 validate

Member newMember = new Member()

.setNo(“100000”)

.setName(“Pamela”)

.setGender(1)

.setMobile(“15011112222”);

Member.create(newMember);

Member.create(newMember, true); // Skip validation

复制代码

4.10 自定义SQL

Member.execute(“DELETE FROM members WHERE name = ?”, “Pamela”);

复制代码

5 复杂SQL 编程指南

ObjectiveSQL 提供的复杂SQL 编程,其实是对SQL 语法的一种抽象和建模,以Java API 形式进行互相作用,使得复杂SQL 不再以字符串的形式出现在Java 中,从而实现动态化SQL 变得清晰易理解,不同的业务系统也可以基于ObjectiveSQL 对自身业务的再抽象和建模,实现SQL 逻辑的复用。

5.1 JOIN 查询

5.1.1 隐式 Join

Member.Table member = Member.asTable();

Order.Table order = Order.asTable();

Select select = new Select();

select.project(member.no, member.name, count().as(“order_count”))

.from(member, order)

.where(member.id.eq(order.memberId))

.groupBy(member.no, member.name);

List members = select.execute(Member.class);

复制代码

SELECT T0.NO , T0.name , COUNT(*) AS order_count

FROM members AS T0, orders AS T1

WHERE (T0.id = T1.member_id )

GROUP BY T0.NO , T0.name

复制代码

5.1.2 显式Join

Member.Table member = Member.asTable();

Order.Table order = Order.asTable();

Select select = new Select();

select.project(member.no, member.name, count().as(“order_count”))

.from(member)

.leftOuterJoin(order, order.memberId.eq(member.id))

.groupBy(member.no, member.name);

List members = select.execute(Member.class);

复制代码

SELECT T0.NO , T0.name , COUNT(*) AS order_count

FROM members AS T0

LEFT OUTER JOIN orders AS T1 ON (T1.member_id = T0.id )

GROUP BY T0.NO , T0.name

复制代码

5.2 分页查询

Member.Table member = Member.asTable();

Order.Table order = Order.asTable();

Paginator paginator = Databases.getPaginator();

Page page = Page.create(0, 20);

Select select = new Select();

select.project(member.no, member.name, count().as(“order_count”))

.from(member, order)

.where(member.id.eq(order.memberId))

.groupBy(member.no, member.name);

PagedList members = paginator.paginate(page, select, Member.class);

复制代码

– Counting SQL

SELECT COUNT(*) AS count_

FROM (

SELECT

T0.NO,

T0.name,

COUNT(*) AS order_count

FROM members AS T0, orders AS T1

WHERE (T0.id = T1.member_id)

GROUP BY T0.NO, T0.name

) T

复制代码

– Querying SQL

SELECT T0.NO, T0.name, COUNT(*) AS order_count

FROM members AS T0, orders AS T1

WHERE (T0.id = T1.member_id)

GROUP BY T0.NO, T0.name

LIMIT 0, 20

复制代码

5.3 复杂表达式查询

ObjectiveSQL 通过运算符重域技术使得Expression 也可以参与各类运算符计算,从而使得Java 代码变得简单易懂,而不是通过各类运算符方法进行计算。ObjectiveSQL 表达式计算时并不能够与SQL 表达完匹配,默认情况下所有表达式均可以进行算术运算,在IntelliJ IDEA 中并不能给出完整的提醒,例如:JoinExpression 也可以进行算术运算,此时在IntelliJ IDEA 中并不会出现语法错误的提醒,但在执行运算过程中会抛出 UnsupportedArithmeticalException,该异常为RuntimeException 的子类。

Order.Table orderTable = Order.asTable();

Select select = new Select();

select.project((sum(orderTable.amount) / sum(orderTable.quantity) * 100).as(“unit_amount”))

.from(orderTable)

.where(orderTable.quantity > 30 &&

orderTable.salesAt.between(“2020-05-01 00:00:00”, “2020-05-02 23:59:59”))

.groupBy(orderTable.memberId);

List orders = select.execute(Order.class);

复制代码

SELECT ((((SUM(T0.amount ) / SUM(T0.quantity ) )) * 100)) AS unit_amount

FROM orders AS T0

WHERE ((T0.quantity > 30)

AND T0.sales_at BETWEEN ‘2020-05-01 00:00:00’ AND ‘2020-05-02 23:59:59’ )

GROUP BY T0.member_id

复制代码

5.4 动态查询

所谓动态查询,实际上就是表达式的构建过程跟随着参数的有无而变化,基于这种使用场景,ObjectiveSQL 设计了一个永真的逻辑表达式EternalExpression ,永真表达式是程序上的一种巧妙设计,使得代码逻辑变得更清晰,即使所有参数均未赋值,整个表达式也会存在一个永的表达,确保最终SQL 语句的正常。

String[] filteredNo = {“202000001”, “202000002”, “202000003”};

int filteredQuantity = 0;

Order.Table orderTable = Order.asTable();

Select select = new Select();

LogicalExpression eternalExpression = new EternalExpression();

if(filteredNo.length > 0) {

eternalExpression = eternalExpression.and(orderTable.no.in(filteredNo));

}

if(filteredQuantity != 0) {

eternalExpression = eternalExpression.and(orderTable > filteredQuantity);

}

select.project((sum(orderTable.amount) / sum(orderTable.quantity) * 100).as(“unit_amount”))

.from(orderTable)

.where(eternalExpression)

.groupBy(orderTable.memberId);

List orders = select.execute(Order.class);

复制代码

SELECT ((((SUM(T0.amount ) / SUM(T0.quantity ) )) * 100)) AS unit_amount

FROM orders AS T0

WHERE ((1 = 1) AND T0.NO IN (‘202000001’, ‘202000002’, ‘202000003’) )

GROUP BY T0.member_id

复制代码

6 高级使用

6.1 日志集成

由于 ObjectiveSQL 无法决定应用系统使用哪一个日志框架,所以ObjectiveSQL 并未集成任何第三方日志框架,确认使用JDK 自身的日志框架,如果应用系统需要使用自身的日志框架,并在系统启动完成后注入ObjectiveSQL,请按下列方式集成(以Slf4j 为例)。

6.1.1 LoggerFactory 扩展实现

========================

public class ObjLoggerFactoryImpl implements LoggerFactory {

private class ObjLoggerImpl implements Logger {

private final org.slf4j.Logger logger;

public ObjLoggerImpl(org.slf4j.Logger logger) {

this.logger = logger;

}

@Override

public void debug(long elapsedTime, String sql, Object[] params) {

logger.debug(createLogContent(elapsedTime, sql, params));

}

@Override

public void info(long elapsedTime, String sql, Object[] params) {

logger.info(createLogContent(elapsedTime, sql, params));

}

@Override

public void error(String message, Throwable throwable) {

logger.error(message, throwable);

}

private String createLogContent(long elapsedTime, String sql, Object[] params) {

String[] paramStrings = Arrays.stream(params)

.map(param -> String.valueOf(param)).toArray(String[]::new);

String paramString = String.join(“,”, paramStrings);

return String.format(“[%dms] %s, with: [%s]”,

elapsedTime, sql, String.join(“,”,

paramString.length() > 100 ? StringUtil

.truncate(paramString, 99) : paramString));

}

}

@Override

public Logger create(Class<?> clazz) {

org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(clazz);

return new ObjLoggerImpl(logger);

}

}

复制代码

6.1.2 普通应用程序注入方式

public class Application {

public static void main(String[] args) {

Databases.installLoggerFactory(new ObjLoggerFactoryImpl());

// others

}

}

复制代码

6.1.3 Spring Boot 应用程序注入方式

@SpringBootApplication

@EnableAutoConfiguration

public class Application {

public static void main(String[] args) {

SpringApplication springApplication = new SpringApplication(Application.class);

springApplication.addListeners(new ApplicationListener() {

@Override

public void onApplicationEvent(ApplicationReadyEvent event) {

Databases.installLoggerFactory(new ObjLoggerFactoryImpl());

}

});

springApplication.run(args);

}

}

复制代码

6.2 基于SQL 语句的对象缓存

应用系统中对时间性不强的数据会进行数据缓存,通常会将数据缓存至Redis 中,针对些特性,可以扩展ObjectiveSQL 的 SQLExecutor 接口轻易实现。

6.2.1 SQLExecutor 扩展实现

public class CacheableSQLExecutor extends DefaultSQLExecutor {

private static final List<Class<? extends Serializable>> CACHEABLE_CLASSES =

Arrays.asList(new Class[]{Member.class});

private static final Integer CACHED_OBJECT_EXPIRED = 60;

private static final String KEY_SHA = “SHA”;

private Jedis jedis = new Jedis(“localhost”, 6379);

private MessageDigest messageDigest;

public CacheableSQLExecutor() {

try {

messageDigest = MessageDigest.getInstance(KEY_SHA);

} catch (NoSuchAlgorithmException e) {

throw new IllegalArgumentException(e.getMessage(), e);

}

}

@Override

public List query(Connection connection, String sql,

TableRowAdapter tableRowAdapter, Object… params)

throws SQLException {

Class<?> domainClass = tableRowAdapter.getDomainModelClass();

if (CACHEABLE_CLASSES.contains(domainClass)) {

if(!Serializable.class.isAssignableFrom(domainClass)) {

throw new IllegalArgumentException(String

.format(“The %s cannot be serialized”));

}

messageDigest.update(sql.getBytes());

String hashedSqlId = new BigInteger(messageDigest.digest()).toString(64);

byte[] rawObjects = jedis.get(hashedSqlId.getBytes());

if (rawObjects != null) {

return (List) SerializationUtils.deserialize(rawObjects);

} else {

List objects = super.query(connection, sql, tableRowAdapter, params);

byte[] encodedObjects = SerializationUtils.serialize(objects);

SetParams expiredParams = SetParams.setParams().ex(CACHED_OBJECT_EXPIRED);

jedis.set(hashedSqlId.getBytes(), encodedObjects, expiredParams);

return objects;

}

}

return super.query(connection, sql, tableRowAdapter, params);

}

}

复制代码

6.2.2 注入方式

public class Application {

public static void main(String[] args) {

Databases.installSqlExecutor(new CacheableSQLExecutor());

// others

}

}

复制代码

Spring Boot 的注入方式去 LogFactory 的注入方式相同

6.3 ColumnTransition 扩展

ColumnTransition 是ObjectiveSQL 对外提供的一种数据类型转的扩展接口,该接口的详细定义请参考:ColumnTransition.java ,以日期形式为例,介绍ColumnTransition 的扩展方式。

public class SqlDateTimeTransition implements ColumnTransition {

@Override

public Object sinking(DatabaseMetaData databaseMetaData, T object,

TableRowAdapter tableRowDescriptor,

String fieldName, FieldValue fieldValue)

throws SQLException {

String databaseName = databaseMetaData.getDatabaseProductName();

if (fieldValue != null && fieldValue.getValue() != null) {

if (SQLite.equals(databaseName) || Oracle.equals(databaseName)) {

return fieldValue;

} else if (PostgreSQL.equals(databaseName)) {

if (fieldValue.getValue() instanceof Timestamp) {

return fieldValue.getValue();

} else if (fieldValue.getValue() instanceof Long) {

Instant value = Instant.ofEpochMilli((Long) fieldValue.getValue());

return Timestamp.from(value);

} else {

return Timestamp.valueOf(String.valueOf(fieldValue.getValue()));

}

} else {

return fieldValue;

}

}

return null;

}

@Override

public Object rising(DatabaseMetaData databaseMetaData,

ResultSetMetaData resultSetMetaData,

T object, TableRowAdapter tableRowDescriptor,

String columnName, Object columnValue) throws SQLException {

String databaseName = databaseMetaData.getDatabaseProductName();

try {

if (columnValue != null) {

if (SQLite.equals(databaseName)) {

Instant value = Instant

.ofEpochMilli(Long.valueOf(String.valueOf(columnValue)))

return Timestamp.from(value);

} else {

return columnValue;

}

}

} catch (DateTimeParseException ex) {

String message = String.format(“Invalid raw DataTime of ‘%s’ from database: %s”,

columnName, columnValue);

throw new IllegalArgumentException(message, ex);

}

return null;

}

}

复制代码

sinking 方法是将Java 中的值,转换为数据库所能接受的值,rising则为将数据库中的值,转换为Java 所能接受的值。
作者:IT小尚
链接:https://juejin.cn/post/7041016816293904420
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后

给大家送一个小福利

附高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、准备面试跳槽、自身职业规划迷茫的朋友们。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

.valueOf(String.valueOf(columnValue)))

return Timestamp.from(value);

} else {

return columnValue;

}

}

} catch (DateTimeParseException ex) {

String message = String.format(“Invalid raw DataTime of ‘%s’ from database: %s”,

columnName, columnValue);

throw new IllegalArgumentException(message, ex);

}

return null;

}

}

复制代码

sinking 方法是将Java 中的值,转换为数据库所能接受的值,rising则为将数据库中的值,转换为Java 所能接受的值。
作者:IT小尚
链接:https://juejin.cn/post/7041016816293904420
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后

给大家送一个小福利

[外链图片转存中…(img-T2aE3rGs-1715080922752)]

附高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、准备面试跳槽、自身职业规划迷茫的朋友们。

[外链图片转存中…(img-WMUMKJ8c-1715080922752)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值