DATAJPA-98 - Formatted sources with Spring Data Eclipse formatting settings.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -2,4 +2,6 @@ target/
|
||||
.settings/
|
||||
.project
|
||||
.classpath
|
||||
.springBeans
|
||||
.springBeans
|
||||
.sonar4clipse
|
||||
*.sonar4clipseExternals
|
||||
291
formatting.xml
Normal file
291
formatting.xml
Normal file
@@ -0,0 +1,291 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="12">
|
||||
<profile kind="CodeFormatterProfile" name="Spring Data" version="12">
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
@@ -26,126 +26,115 @@ import javax.persistence.TemporalType;
|
||||
import org.joda.time.DateTime;
|
||||
import org.springframework.data.domain.Auditable;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class for auditable entities. Stores the audition values in
|
||||
* persistent fields.
|
||||
* Abstract base class for auditable entities. Stores the audition values in persistent fields.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @param <U> the auditing type. Typically some kind of user.
|
||||
* @param <PK> the type of the auditing type's idenifier
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractAuditable<U, PK extends Serializable> extends
|
||||
AbstractPersistable<PK> implements Auditable<U, PK> {
|
||||
public abstract class AbstractAuditable<U, PK extends Serializable> extends AbstractPersistable<PK> implements
|
||||
Auditable<U, PK> {
|
||||
|
||||
private static final long serialVersionUID = 141481953116476081L;
|
||||
private static final long serialVersionUID = 141481953116476081L;
|
||||
|
||||
@OneToOne
|
||||
private U createdBy;
|
||||
@OneToOne
|
||||
private U createdBy;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createdDate;
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createdDate;
|
||||
|
||||
@OneToOne
|
||||
private U lastModifiedBy;
|
||||
@OneToOne
|
||||
private U lastModifiedBy;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastModifiedDate;
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastModifiedDate;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Auditable#getCreatedBy()
|
||||
*/
|
||||
public U getCreatedBy() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Auditable#getCreatedBy()
|
||||
*/
|
||||
public U getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
return createdBy;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.domain.Auditable#setCreatedBy(java.lang.Object)
|
||||
*/
|
||||
public void setCreatedBy(final U createdBy) {
|
||||
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.domain.Auditable#setCreatedBy(java.lang.Object)
|
||||
*/
|
||||
public void setCreatedBy(final U createdBy) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Auditable#getCreatedDate()
|
||||
*/
|
||||
public DateTime getCreatedDate() {
|
||||
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
return null == createdDate ? null : new DateTime(createdDate);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.domain.Auditable#setCreatedDate(org.joda.time
|
||||
* .DateTime)
|
||||
*/
|
||||
public void setCreatedDate(final DateTime createdDate) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Auditable#getCreatedDate()
|
||||
*/
|
||||
public DateTime getCreatedDate() {
|
||||
this.createdDate = null == createdDate ? null : createdDate.toDate();
|
||||
}
|
||||
|
||||
return null == createdDate ? null : new DateTime(createdDate);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Auditable#getLastModifiedBy()
|
||||
*/
|
||||
public U getLastModifiedBy() {
|
||||
|
||||
return lastModifiedBy;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.domain.Auditable#setCreatedDate(org.joda.time
|
||||
* .DateTime)
|
||||
*/
|
||||
public void setCreatedDate(final DateTime createdDate) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.domain.Auditable#setLastModifiedBy(java.lang
|
||||
* .Object)
|
||||
*/
|
||||
public void setLastModifiedBy(final U lastModifiedBy) {
|
||||
|
||||
this.createdDate = null == createdDate ? null : createdDate.toDate();
|
||||
}
|
||||
this.lastModifiedBy = lastModifiedBy;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Auditable#getLastModifiedDate()
|
||||
*/
|
||||
public DateTime getLastModifiedDate() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Auditable#getLastModifiedBy()
|
||||
*/
|
||||
public U getLastModifiedBy() {
|
||||
return null == lastModifiedDate ? null : new DateTime(lastModifiedDate);
|
||||
}
|
||||
|
||||
return lastModifiedBy;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.domain.Auditable#setLastModifiedDate(org.joda
|
||||
* .time.DateTime)
|
||||
*/
|
||||
public void setLastModifiedDate(final DateTime lastModifiedDate) {
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.domain.Auditable#setLastModifiedBy(java.lang
|
||||
* .Object)
|
||||
*/
|
||||
public void setLastModifiedBy(final U lastModifiedBy) {
|
||||
|
||||
this.lastModifiedBy = lastModifiedBy;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Auditable#getLastModifiedDate()
|
||||
*/
|
||||
public DateTime getLastModifiedDate() {
|
||||
|
||||
return null == lastModifiedDate ? null : new DateTime(lastModifiedDate);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.domain.Auditable#setLastModifiedDate(org.joda
|
||||
* .time.DateTime)
|
||||
*/
|
||||
public void setLastModifiedDate(final DateTime lastModifiedDate) {
|
||||
|
||||
this.lastModifiedDate =
|
||||
null == lastModifiedDate ? null : lastModifiedDate.toDate();
|
||||
}
|
||||
this.lastModifiedDate = null == lastModifiedDate ? null : lastModifiedDate.toDate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,110 +24,100 @@ import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.springframework.data.domain.Persistable;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class for entities. Allows parameterization of id type, chooses
|
||||
* auto-generation and implements {@link #equals(Object)} and
|
||||
* {@link #hashCode()} based on that id.
|
||||
* Abstract base class for entities. Allows parameterization of id type, chooses auto-generation and implements
|
||||
* {@link #equals(Object)} and {@link #hashCode()} based on that id.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @param <PK> the the of the entity
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractPersistable<PK extends Serializable> implements
|
||||
Persistable<PK> {
|
||||
public abstract class AbstractPersistable<PK extends Serializable> implements Persistable<PK> {
|
||||
|
||||
private static final long serialVersionUID = -5554308939380869754L;
|
||||
private static final long serialVersionUID = -5554308939380869754L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private PK id;
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private PK id;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Persistable#getId()
|
||||
*/
|
||||
public PK getId() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Persistable#getId()
|
||||
*/
|
||||
public PK getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
/**
|
||||
* Sets the id of the entity.
|
||||
*
|
||||
* @param id the id to set
|
||||
*/
|
||||
protected void setId(final PK id) {
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id of the entity.
|
||||
*
|
||||
* @param id the id to set
|
||||
*/
|
||||
protected void setId(final PK id) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Persistable#isNew()
|
||||
*/
|
||||
public boolean isNew() {
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
return null == getId();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Persistable#isNew()
|
||||
*/
|
||||
public boolean isNew() {
|
||||
return String.format("Entity of type %s with id: %s", this.getClass().getName(), getId());
|
||||
}
|
||||
|
||||
return null == getId();
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (null == obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return String.format("Entity of type %s with id: %s", this.getClass()
|
||||
.getName(), getId());
|
||||
}
|
||||
if (!getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AbstractPersistable<?> that = (AbstractPersistable<?>) obj;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return null == this.getId() ? false : this.getId().equals(that.getId());
|
||||
}
|
||||
|
||||
if (null == obj) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
int hashCode = 17;
|
||||
|
||||
if (!getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
hashCode += null == getId() ? 0 : getId().hashCode() * 31;
|
||||
|
||||
AbstractPersistable<?> that = (AbstractPersistable<?>) obj;
|
||||
|
||||
return null == this.getId() ? false : this.getId().equals(that.getId());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashCode = 17;
|
||||
|
||||
hashCode += null == getId() ? 0 : getId().hashCode() * 31;
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
|
||||
/**
|
||||
* Specification in the sense of Domain Driven Design.
|
||||
*
|
||||
@@ -28,14 +27,13 @@ import javax.persistence.criteria.Root;
|
||||
*/
|
||||
public interface Specification<T> {
|
||||
|
||||
/**
|
||||
* Creates a WHERE clause for a query of the referenced entity in form of a
|
||||
* {@link Predicate} for the given {@link Root} and {@link CriteriaQuery}.
|
||||
*
|
||||
* @param root
|
||||
* @param query
|
||||
* @return a {@link Predicate}, must not be {@literal null}.
|
||||
*/
|
||||
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
|
||||
CriteriaBuilder cb);
|
||||
/**
|
||||
* Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
|
||||
* {@link Root} and {@link CriteriaQuery}.
|
||||
*
|
||||
* @param root
|
||||
* @param query
|
||||
* @return a {@link Predicate}, must not be {@literal null}.
|
||||
*/
|
||||
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to easily combine {@link Specification} instances.
|
||||
*
|
||||
@@ -28,106 +27,92 @@ import javax.persistence.criteria.Root;
|
||||
*/
|
||||
public class Specifications<T> implements Specification<T> {
|
||||
|
||||
private final Specification<T> spec;
|
||||
private final Specification<T> spec;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Specifications} wrapper for the given {@link Specification}.
|
||||
*
|
||||
* @param spec
|
||||
*/
|
||||
private Specifications(Specification<T> spec) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Specifications} wrapper for the given
|
||||
* {@link Specification}.
|
||||
*
|
||||
* @param spec
|
||||
*/
|
||||
private Specifications(Specification<T> spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
this.spec = spec;
|
||||
}
|
||||
/**
|
||||
* Simple static factory method to add some syntactic sugar around a {@link Specification}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param spec
|
||||
* @return
|
||||
*/
|
||||
public static <T> Specifications<T> where(Specification<T> spec) {
|
||||
|
||||
return new Specifications<T>(spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple static factory method to add some syntactic sugar around a
|
||||
* {@link Specification}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param spec
|
||||
* @return
|
||||
*/
|
||||
public static <T> Specifications<T> where(Specification<T> spec) {
|
||||
/**
|
||||
* ANDs the given {@link Specification} to the current one.
|
||||
*
|
||||
* @param other
|
||||
* @return
|
||||
*/
|
||||
public Specifications<T> and(final Specification<T> other) {
|
||||
|
||||
return new Specifications<T>(spec);
|
||||
}
|
||||
return new Specifications<T>(new Specification<T>() {
|
||||
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
|
||||
/**
|
||||
* ANDs the given {@link Specification} to the current one.
|
||||
*
|
||||
* @param other
|
||||
* @return
|
||||
*/
|
||||
public Specifications<T> and(final Specification<T> other) {
|
||||
return builder.and(spec.toPredicate(root, query, builder), other.toPredicate(root, query, builder));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new Specifications<T>(new Specification<T>() {
|
||||
/**
|
||||
* ORs the given specification to the current one.
|
||||
*
|
||||
* @param other
|
||||
* @return
|
||||
*/
|
||||
public Specifications<T> or(final Specification<T> other) {
|
||||
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
|
||||
CriteriaBuilder builder) {
|
||||
return new Specifications<T>(new Specification<T>() {
|
||||
|
||||
return builder.and(spec.toPredicate(root, query, builder),
|
||||
other.toPredicate(root, query, builder));
|
||||
}
|
||||
});
|
||||
}
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
|
||||
return builder.or(spec.toPredicate(root, query, builder), other.toPredicate(root, query, builder));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* ORs the given specification to the current one.
|
||||
*
|
||||
* @param other
|
||||
* @return
|
||||
*/
|
||||
public Specifications<T> or(final Specification<T> other) {
|
||||
/**
|
||||
* Negates the given {@link Specification}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param spec
|
||||
* @return
|
||||
*/
|
||||
public static <T> Specifications<T> not(final Specification<T> spec) {
|
||||
|
||||
return new Specifications<T>(new Specification<T>() {
|
||||
return new Specifications<T>(spec) {
|
||||
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
|
||||
CriteriaBuilder builder) {
|
||||
@Override
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
|
||||
return builder.or(spec.toPredicate(root, query, builder),
|
||||
other.toPredicate(root, query, builder));
|
||||
}
|
||||
});
|
||||
}
|
||||
return builder.not(spec.toPredicate(root, query, builder));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.
|
||||
* persistence.criteria.Root, javax.persistence.criteria.CriteriaQuery,
|
||||
* javax.persistence.criteria.CriteriaBuilder)
|
||||
*/
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
|
||||
/**
|
||||
* Negates the given {@link Specification}.
|
||||
*
|
||||
* @param <T>
|
||||
* @param spec
|
||||
* @return
|
||||
*/
|
||||
public static <T> Specifications<T> not(final Specification<T> spec) {
|
||||
|
||||
return new Specifications<T>(spec) {
|
||||
|
||||
@Override
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
|
||||
CriteriaBuilder builder) {
|
||||
|
||||
return builder.not(spec.toPredicate(root, query, builder));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.
|
||||
* persistence.criteria.Root, javax.persistence.criteria.CriteriaQuery,
|
||||
* javax.persistence.criteria.CriteriaBuilder)
|
||||
*/
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
|
||||
CriteriaBuilder builder) {
|
||||
|
||||
return spec.toPredicate(root, query, builder);
|
||||
}
|
||||
return spec.toPredicate(root, query, builder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,82 +27,68 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* {@link BeanFactoryPostProcessor} to add a {@code depends-on} from a
|
||||
* {@link org.springframework.orm.jpa.LocalEntityManagerFactoryBean} or
|
||||
* {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean}
|
||||
* towards the aspect bean configured via
|
||||
* {@code <context:spring-configured>}. This has to be done to ensure the
|
||||
* aspect is up and running <em>before</em> the
|
||||
* {@link javax.persistence.EntityManagerFactory} gets created as this already
|
||||
* instantiates entity listeners and we need to get injection into
|
||||
* {@link org.springframework.beans.factory.annotation.Configurable} to work in
|
||||
* them.
|
||||
* {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} towards the aspect bean configured via
|
||||
* {@code <context:spring-configured>}. This has to be done to ensure the aspect is up and running <em>before</em>
|
||||
* the {@link javax.persistence.EntityManagerFactory} gets created as this already instantiates entity listeners and we
|
||||
* need to get injection into {@link org.springframework.beans.factory.annotation.Configurable} to work in them.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AuditingBeanFactoryPostProcessor implements
|
||||
BeanFactoryPostProcessor {
|
||||
public class AuditingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
|
||||
|
||||
static final String BEAN_CONFIGURER_ASPECT_BEAN_NAME =
|
||||
"org.springframework.context.config.internalBeanConfigurerAspect";
|
||||
static final String BEAN_CONFIGURER_ASPECT_BEAN_NAME = "org.springframework.context.config.internalBeanConfigurerAspect";
|
||||
|
||||
private static final String JPA_PACKAGE = "org.springframework.orm.jpa.";
|
||||
private static final List<String> CLASSES_TO_DEPEND = Arrays.asList(
|
||||
JPA_PACKAGE + "LocalContainerEntityManagerFactoryBean", JPA_PACKAGE
|
||||
+ "LocalEntityManagerFactoryBean");
|
||||
private static final String JPA_PACKAGE = "org.springframework.orm.jpa.";
|
||||
private static final List<String> CLASSES_TO_DEPEND = Arrays.asList(JPA_PACKAGE
|
||||
+ "LocalContainerEntityManagerFactoryBean", JPA_PACKAGE + "LocalEntityManagerFactoryBean");
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#
|
||||
* postProcessBeanFactory
|
||||
* (org.springframework.beans.factory.config.ConfigurableListableBeanFactory
|
||||
* )
|
||||
*/
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#
|
||||
* postProcessBeanFactory
|
||||
* (org.springframework.beans.factory.config.ConfigurableListableBeanFactory
|
||||
* )
|
||||
*/
|
||||
public void postProcessBeanFactory(
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
if (!isSpringConfigured(beanFactory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSpringConfigured(beanFactory)) {
|
||||
return;
|
||||
}
|
||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||
|
||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
|
||||
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
|
||||
if (CLASSES_TO_DEPEND.contains(definition.getBeanClassName())) {
|
||||
definition.setDependsOn(StringUtils.addStringToArray(definition.getDependsOn(),
|
||||
BEAN_CONFIGURER_ASPECT_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
if (CLASSES_TO_DEPEND.contains(definition.getBeanClassName())) {
|
||||
definition.setDependsOn(StringUtils.addStringToArray(
|
||||
definition.getDependsOn(),
|
||||
BEAN_CONFIGURER_ASPECT_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
for (String beanName : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, AuditorAware.class, true,
|
||||
false)) {
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
|
||||
definition.setLazyInit(true);
|
||||
}
|
||||
}
|
||||
|
||||
for (String beanName : BeanFactoryUtils
|
||||
.beanNamesForTypeIncludingAncestors(beanFactory,
|
||||
AuditorAware.class, true, false)) {
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
|
||||
definition.setLazyInit(true);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns whether we have a bean factory for which {@code <context:spring-configured>} was activated.
|
||||
*
|
||||
* @param factory
|
||||
* @return
|
||||
*/
|
||||
private boolean isSpringConfigured(BeanFactory factory) {
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether we have a bean factory for which
|
||||
* {@code <context:spring-configured>} was activated.
|
||||
*
|
||||
* @param factory
|
||||
* @return
|
||||
*/
|
||||
private boolean isSpringConfigured(BeanFactory factory) {
|
||||
|
||||
try {
|
||||
factory.getBean(BEAN_CONFIGURER_ASPECT_BEAN_NAME);
|
||||
return true;
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
try {
|
||||
factory.getBean(BEAN_CONFIGURER_ASPECT_BEAN_NAME);
|
||||
return true;
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,9 @@ import org.springframework.data.domain.Auditable;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* JPA entity listener to capture auditing information on persiting and updating
|
||||
* entities. To get this one flying be sure you configure it as entity listener
|
||||
* in your {@code orm.xml} as follows:
|
||||
* JPA entity listener to capture auditing information on persiting and updating entities. To get this one flying be
|
||||
* sure you configure it as entity listener in your {@code orm.xml} as follows:
|
||||
*
|
||||
* <pre>
|
||||
* <persistence-unit-metadata>
|
||||
@@ -54,167 +52,150 @@ import org.springframework.util.Assert;
|
||||
@Configurable
|
||||
public class AuditingEntityListener<T> implements InitializingBean {
|
||||
|
||||
private static final Logger LOG = LoggerFactory
|
||||
.getLogger(AuditingEntityListener.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AuditingEntityListener.class);
|
||||
|
||||
private AuditorAware<T> auditorAware;
|
||||
private AuditorAware<T> auditorAware;
|
||||
|
||||
private boolean dateTimeForNow = true;
|
||||
private boolean modifyOnCreation = true;
|
||||
private boolean dateTimeForNow = true;
|
||||
private boolean modifyOnCreation = true;
|
||||
|
||||
/**
|
||||
* Setter to inject a {@code AuditorAware} component to retrieve the current auditor.
|
||||
*
|
||||
* @param auditorAware the auditorAware to set
|
||||
*/
|
||||
public void setAuditorAware(final AuditorAware<T> auditorAware) {
|
||||
|
||||
/**
|
||||
* Setter to inject a {@code AuditorAware} component to retrieve the current
|
||||
* auditor.
|
||||
*
|
||||
* @param auditorAware the auditorAware to set
|
||||
*/
|
||||
public void setAuditorAware(final AuditorAware<T> auditorAware) {
|
||||
Assert.notNull(auditorAware);
|
||||
this.auditorAware = auditorAware;
|
||||
}
|
||||
|
||||
Assert.notNull(auditorAware);
|
||||
this.auditorAware = auditorAware;
|
||||
}
|
||||
/**
|
||||
* Setter do determine if {@link Auditable#setCreatedDate(DateTime)} and
|
||||
* {@link Auditable#setLastModifiedDate(DateTime)} shall be filled with the current Java time. Defaults to
|
||||
* {@code true}. One might set this to {@code false} to use database features to set entity time.
|
||||
*
|
||||
* @param dateTimeForNow the dateTimeForNow to set
|
||||
*/
|
||||
public void setDateTimeForNow(boolean dateTimeForNow) {
|
||||
|
||||
this.dateTimeForNow = dateTimeForNow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter do determine if {@link Auditable#setCreatedDate(DateTime)} and
|
||||
* {@link Auditable#setLastModifiedDate(DateTime)} shall be filled with the
|
||||
* current Java time. Defaults to {@code true}. One might set this to
|
||||
* {@code false} to use database features to set entity time.
|
||||
*
|
||||
* @param dateTimeForNow the dateTimeForNow to set
|
||||
*/
|
||||
public void setDateTimeForNow(boolean dateTimeForNow) {
|
||||
/**
|
||||
* Set this to false if you want to treat entity creation as modification and thus set the current date as
|
||||
* modification date, too. Defaults to {@code true}.
|
||||
*
|
||||
* @param modifyOnCreation if modification information shall be set on creation, too
|
||||
*/
|
||||
public void setModifyOnCreation(final boolean modifyOnCreation) {
|
||||
|
||||
this.dateTimeForNow = dateTimeForNow;
|
||||
}
|
||||
this.modifyOnCreation = modifyOnCreation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets modification and creation date and auditor on the target object in case it implements {@link Auditable} on
|
||||
* persist events.
|
||||
*
|
||||
* @param target
|
||||
*/
|
||||
@PrePersist
|
||||
public void touchForCreate(Object target) {
|
||||
|
||||
/**
|
||||
* Set this to false if you want to treat entity creation as modification
|
||||
* and thus set the current date as modification date, too. Defaults to
|
||||
* {@code true}.
|
||||
*
|
||||
* @param modifyOnCreation if modification information shall be set on
|
||||
* creation, too
|
||||
*/
|
||||
public void setModifyOnCreation(final boolean modifyOnCreation) {
|
||||
touch(target, true);
|
||||
}
|
||||
|
||||
this.modifyOnCreation = modifyOnCreation;
|
||||
}
|
||||
/**
|
||||
* Sets modification and creation date and auditor on the target object in case it implements {@link Auditable} on
|
||||
* update events.
|
||||
*
|
||||
* @param target
|
||||
*/
|
||||
@PreUpdate
|
||||
public void touchForUpdate(Object target) {
|
||||
|
||||
touch(target, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets modification and creation date and auditor on the target object in
|
||||
* case it implements {@link Auditable} on persist events.
|
||||
*
|
||||
* @param target
|
||||
*/
|
||||
@PrePersist
|
||||
public void touchForCreate(Object target) {
|
||||
private void touch(Object target, boolean isNew) {
|
||||
|
||||
touch(target, true);
|
||||
}
|
||||
if (!(target instanceof Auditable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Auditable<T, ?> auditable = (Auditable<T, ?>) target;
|
||||
|
||||
/**
|
||||
* Sets modification and creation date and auditor on the target object in
|
||||
* case it implements {@link Auditable} on update events.
|
||||
*
|
||||
* @param target
|
||||
*/
|
||||
@PreUpdate
|
||||
public void touchForUpdate(Object target) {
|
||||
T auditor = touchAuditor(auditable, isNew);
|
||||
DateTime now = dateTimeForNow ? touchDate(auditable, isNew) : null;
|
||||
|
||||
touch(target, false);
|
||||
}
|
||||
Object defaultedNow = now == null ? "not set" : now;
|
||||
Object defaultedAuditor = auditor == null ? "unknown" : auditor;
|
||||
|
||||
LOG.debug("Touched {} - Last modification at {} by {}", new Object[] { auditable, defaultedNow, defaultedAuditor });
|
||||
}
|
||||
|
||||
private void touch(Object target, boolean isNew) {
|
||||
/**
|
||||
* Sets modifying and creating auditioner. Creating auditioner is only set on new auditables.
|
||||
*
|
||||
* @param auditable
|
||||
* @return
|
||||
*/
|
||||
private T touchAuditor(final Auditable<T, ?> auditable, boolean isNew) {
|
||||
|
||||
if (!(target instanceof Auditable)) {
|
||||
return;
|
||||
}
|
||||
if (null == auditorAware) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Auditable<T, ?> auditable = (Auditable<T, ?>) target;
|
||||
T auditor = auditorAware.getCurrentAuditor();
|
||||
|
||||
T auditor = touchAuditor(auditable, isNew);
|
||||
DateTime now = dateTimeForNow ? touchDate(auditable, isNew) : null;
|
||||
if (isNew) {
|
||||
|
||||
Object defaultedNow = now == null ? "not set" : now;
|
||||
Object defaultedAuditor = auditor == null ? "unknown" : auditor;
|
||||
auditable.setCreatedBy(auditor);
|
||||
|
||||
LOG.debug("Touched {} - Last modification at {} by {}", new Object[] {
|
||||
auditable, defaultedNow, defaultedAuditor });
|
||||
}
|
||||
if (!modifyOnCreation) {
|
||||
return auditor;
|
||||
}
|
||||
}
|
||||
|
||||
auditable.setLastModifiedBy(auditor);
|
||||
|
||||
/**
|
||||
* Sets modifying and creating auditioner. Creating auditioner is only set
|
||||
* on new auditables.
|
||||
*
|
||||
* @param auditable
|
||||
* @return
|
||||
*/
|
||||
private T touchAuditor(final Auditable<T, ?> auditable, boolean isNew) {
|
||||
return auditor;
|
||||
}
|
||||
|
||||
if (null == auditorAware) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Touches the auditable regarding modification and creation date. Creation date is only set on new auditables.
|
||||
*
|
||||
* @param auditable
|
||||
* @return
|
||||
*/
|
||||
private DateTime touchDate(final Auditable<T, ?> auditable, boolean isNew) {
|
||||
|
||||
T auditor = auditorAware.getCurrentAuditor();
|
||||
DateTime now = new DateTime();
|
||||
|
||||
if (isNew) {
|
||||
if (isNew) {
|
||||
auditable.setCreatedDate(now);
|
||||
|
||||
auditable.setCreatedBy(auditor);
|
||||
if (!modifyOnCreation) {
|
||||
return now;
|
||||
}
|
||||
}
|
||||
|
||||
if (!modifyOnCreation) {
|
||||
return auditor;
|
||||
}
|
||||
}
|
||||
auditable.setLastModifiedDate(now);
|
||||
|
||||
auditable.setLastModifiedBy(auditor);
|
||||
return now;
|
||||
}
|
||||
|
||||
return auditor;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
|
||||
/**
|
||||
* Touches the auditable regarding modification and creation date. Creation
|
||||
* date is only set on new auditables.
|
||||
*
|
||||
* @param auditable
|
||||
* @return
|
||||
*/
|
||||
private DateTime touchDate(final Auditable<T, ?> auditable, boolean isNew) {
|
||||
|
||||
DateTime now = new DateTime();
|
||||
|
||||
if (isNew) {
|
||||
auditable.setCreatedDate(now);
|
||||
|
||||
if (!modifyOnCreation) {
|
||||
return now;
|
||||
}
|
||||
}
|
||||
|
||||
auditable.setLastModifiedDate(now);
|
||||
|
||||
return now;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
if (auditorAware == null) {
|
||||
LOG.debug("No AuditorAware set! Auditing will not be applied!");
|
||||
}
|
||||
}
|
||||
if (auditorAware == null) {
|
||||
LOG.debug("No AuditorAware set! Auditing will not be applied!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,64 +23,55 @@ import javax.persistence.EntityManager;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
|
||||
/**
|
||||
* JPA specific extension of
|
||||
* {@link org.springframework.data.repository.Repository}.
|
||||
* JPA specific extension of {@link org.springframework.data.repository.Repository}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface JpaRepository<T, ID extends Serializable> extends
|
||||
PagingAndSortingRepository<T, ID> {
|
||||
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#findAll()
|
||||
*/
|
||||
List<T> findAll();
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#findAll()
|
||||
*/
|
||||
List<T> findAll();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.PagingAndSortingRepository#findAll
|
||||
* (org.springframework.data.domain.Sort)
|
||||
*/
|
||||
List<T> findAll(Sort sort);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.PagingAndSortingRepository#findAll
|
||||
* (org.springframework.data.domain.Sort)
|
||||
*/
|
||||
List<T> findAll(Sort sort);
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#save(java.lang.Iterable)
|
||||
*/
|
||||
List<T> save(Iterable<? extends T> entities);
|
||||
|
||||
/**
|
||||
* Flushes all pending changes to the database.
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#save(java.lang.Iterable)
|
||||
*/
|
||||
List<T> save(Iterable<? extends T> entities);
|
||||
/**
|
||||
* Saves an entity and flushes changes instantly.
|
||||
*
|
||||
* @param entity
|
||||
* @return the saved entity
|
||||
*/
|
||||
T saveAndFlush(T entity);
|
||||
|
||||
|
||||
/**
|
||||
* Flushes all pending changes to the database.
|
||||
*/
|
||||
void flush();
|
||||
|
||||
|
||||
/**
|
||||
* Saves an entity and flushes changes instantly.
|
||||
*
|
||||
* @param entity
|
||||
* @return the saved entity
|
||||
*/
|
||||
T saveAndFlush(T entity);
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the given entities in a batch which means it will create a single
|
||||
* {@link Query}. Assume that we will clear the {@link EntityManager} after
|
||||
* the call.
|
||||
*
|
||||
* @param entities
|
||||
*/
|
||||
void deleteInBatch(Iterable<T> entities);
|
||||
/**
|
||||
* Deletes the given entities in a batch which means it will create a single {@link Query}. Assume that we will clear
|
||||
* the {@link EntityManager} after the call.
|
||||
*
|
||||
* @param entities
|
||||
*/
|
||||
void deleteInBatch(Iterable<T> entities);
|
||||
}
|
||||
|
||||
@@ -22,61 +22,52 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to allow execution of {@link Specification}s based on the JPA
|
||||
* criteria API.
|
||||
* Interface to allow execution of {@link Specification}s based on the JPA criteria API.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface JpaSpecificationExecutor<T> {
|
||||
|
||||
/**
|
||||
* Returns a single entity matching the given {@link Specification}.
|
||||
*
|
||||
* @param spec
|
||||
* @return
|
||||
*/
|
||||
T findOne(Specification<T> spec);
|
||||
/**
|
||||
* Returns a single entity matching the given {@link Specification}.
|
||||
*
|
||||
* @param spec
|
||||
* @return
|
||||
*/
|
||||
T findOne(Specification<T> spec);
|
||||
|
||||
/**
|
||||
* Returns all entities matching the given {@link Specification}.
|
||||
*
|
||||
* @param spec
|
||||
* @return
|
||||
*/
|
||||
List<T> findAll(Specification<T> spec);
|
||||
|
||||
/**
|
||||
* Returns all entities matching the given {@link Specification}.
|
||||
*
|
||||
* @param spec
|
||||
* @return
|
||||
*/
|
||||
List<T> findAll(Specification<T> spec);
|
||||
/**
|
||||
* Returns a {@link Page} of entities matching the given {@link Specification}.
|
||||
*
|
||||
* @param spec
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
Page<T> findAll(Specification<T> spec, Pageable pageable);
|
||||
|
||||
/**
|
||||
* Returns all entities matching the given {@link Specification} and {@link Sort}.
|
||||
*
|
||||
* @param spec
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
List<T> findAll(Specification<T> spec, Sort sort);
|
||||
|
||||
/**
|
||||
* Returns a {@link Page} of entities matching the given
|
||||
* {@link Specification}.
|
||||
*
|
||||
* @param spec
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
Page<T> findAll(Specification<T> spec, Pageable pageable);
|
||||
|
||||
|
||||
/**
|
||||
* Returns all entities matching the given {@link Specification} and
|
||||
* {@link Sort}.
|
||||
*
|
||||
* @param spec
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
List<T> findAll(Specification<T> spec, Sort sort);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of instances that the given {@link Specification} will
|
||||
* return.
|
||||
*
|
||||
* @param spec the {@link Specification} to count instances for
|
||||
* @return the number of instances
|
||||
*/
|
||||
long count(Specification<T> spec);
|
||||
/**
|
||||
* Returns the number of instances that the given {@link Specification} will return.
|
||||
*
|
||||
* @param spec the {@link Specification} to count instances for
|
||||
* @return the number of instances
|
||||
*/
|
||||
long count(Specification<T> spec);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a method should be regarded as modifying query.
|
||||
*
|
||||
@@ -32,11 +31,10 @@ import java.lang.annotation.Target;
|
||||
@Documented
|
||||
public @interface Modifying {
|
||||
|
||||
/**
|
||||
* Defines whether we should clear the underlying persistence context after
|
||||
* excuting the modifying query.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean clearAutomatically() default false;
|
||||
/**
|
||||
* Defines whether we should clear the underlying persistence context after excuting the modifying query.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean clearAutomatically() default false;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Annotation to declare finder queries directly on repository methods.
|
||||
*
|
||||
@@ -32,8 +31,7 @@ import java.lang.annotation.Target;
|
||||
@Documented
|
||||
public @interface Query {
|
||||
|
||||
String value() default "";
|
||||
String value() default "";
|
||||
|
||||
|
||||
String countQuery() default "";
|
||||
String countQuery() default "";
|
||||
}
|
||||
|
||||
@@ -22,13 +22,11 @@ import java.lang.annotation.Target;
|
||||
|
||||
import javax.persistence.QueryHint;
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper annotation to allow {@link QueryHint} annotations to be bound to
|
||||
* methods. It will be evaluated when using {@link Query} on a query method or
|
||||
* if you derive the query from the method name. If you rely on named queries
|
||||
* either use the XML or annotation based way to declare {@link QueryHint}s in
|
||||
* combination with the actual named query declaration.
|
||||
* Wrapper annotation to allow {@link QueryHint} annotations to be bound to methods. It will be evaluated when using
|
||||
* {@link Query} on a query method or if you derive the query from the method name. If you rely on named queries either
|
||||
* use the XML or annotation based way to declare {@link QueryHint}s in combination with the actual named query
|
||||
* declaration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -36,5 +34,5 @@ import javax.persistence.QueryHint;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface QueryHints {
|
||||
|
||||
QueryHint[] value() default {};
|
||||
QueryHint[] value() default {};
|
||||
}
|
||||
|
||||
@@ -29,117 +29,94 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} for the {@code auditing} element. Sets up an
|
||||
* AudE
|
||||
* {@link BeanDefinitionParser} for the {@code auditing} element. Sets up an AudE
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AuditingBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
static final String AUDITING_ENTITY_LISTENER_CLASS_NAME =
|
||||
"org.springframework.data.jpa.domain.support.AuditingEntityListener";
|
||||
private static final String AUDITING_BFPP_CLASS_NAME =
|
||||
"org.springframework.data.jpa.domain.support.AuditingBeanFactoryPostProcessor";
|
||||
static final String AUDITING_ENTITY_LISTENER_CLASS_NAME = "org.springframework.data.jpa.domain.support.AuditingEntityListener";
|
||||
private static final String AUDITING_BFPP_CLASS_NAME = "org.springframework.data.jpa.domain.support.AuditingBeanFactoryPostProcessor";
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.
|
||||
* w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parser) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.
|
||||
* w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parser) {
|
||||
new SpringConfiguredBeanDefinitionParser().parse(element, parser);
|
||||
|
||||
new SpringConfiguredBeanDefinitionParser().parse(element, parser);
|
||||
BeanDefinitionBuilder builder = rootBeanDefinition(AUDITING_ENTITY_LISTENER_CLASS_NAME);
|
||||
builder.setScope("prototype");
|
||||
|
||||
BeanDefinitionBuilder builder =
|
||||
rootBeanDefinition(AUDITING_ENTITY_LISTENER_CLASS_NAME);
|
||||
builder.setScope("prototype");
|
||||
String auditorAwareRef = element.getAttribute("auditor-aware-ref");
|
||||
|
||||
String auditorAwareRef = element.getAttribute("auditor-aware-ref");
|
||||
if (StringUtils.hasText(auditorAwareRef)) {
|
||||
builder.addPropertyValue("auditorAware", createLazyInitTargetSourceBeanDefinition(auditorAwareRef));
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(auditorAwareRef)) {
|
||||
builder.addPropertyValue("auditorAware",
|
||||
createLazyInitTargetSourceBeanDefinition(auditorAwareRef));
|
||||
}
|
||||
builder.addPropertyValue("dateTimeForNow", element.getAttribute("set-dates"));
|
||||
|
||||
builder.addPropertyValue("dateTimeForNow",
|
||||
element.getAttribute("set-dates"));
|
||||
registerInfrastructureBeanWithId(builder.getRawBeanDefinition(), AUDITING_ENTITY_LISTENER_CLASS_NAME, parser,
|
||||
element);
|
||||
|
||||
registerInfrastructureBeanWithId(builder.getRawBeanDefinition(),
|
||||
AUDITING_ENTITY_LISTENER_CLASS_NAME, parser, element);
|
||||
RootBeanDefinition def = new RootBeanDefinition();
|
||||
def.setBeanClassName(AUDITING_BFPP_CLASS_NAME);
|
||||
registerInfrastructureBeanWithId(def, AUDITING_BFPP_CLASS_NAME, parser, element);
|
||||
|
||||
RootBeanDefinition def = new RootBeanDefinition();
|
||||
def.setBeanClassName(AUDITING_BFPP_CLASS_NAME);
|
||||
registerInfrastructureBeanWithId(def, AUDITING_BFPP_CLASS_NAME, parser,
|
||||
element);
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
private BeanDefinition createLazyInitTargetSourceBeanDefinition(String auditorAwareRef) {
|
||||
|
||||
BeanDefinitionBuilder targetSourceBuilder = rootBeanDefinition(LazyInitTargetSource.class);
|
||||
targetSourceBuilder.addPropertyValue("targetBeanName", auditorAwareRef);
|
||||
|
||||
private BeanDefinition createLazyInitTargetSourceBeanDefinition(
|
||||
String auditorAwareRef) {
|
||||
BeanDefinitionBuilder builder = rootBeanDefinition(ProxyFactoryBean.class);
|
||||
builder.addPropertyValue("targetSource", targetSourceBuilder.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder targetSourceBuilder =
|
||||
rootBeanDefinition(LazyInitTargetSource.class);
|
||||
targetSourceBuilder.addPropertyValue("targetBeanName", auditorAwareRef);
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder builder =
|
||||
rootBeanDefinition(ProxyFactoryBean.class);
|
||||
builder.addPropertyValue("targetSource",
|
||||
targetSourceBuilder.getBeanDefinition());
|
||||
private void registerInfrastructureBeanWithId(AbstractBeanDefinition def, String id, ParserContext context,
|
||||
Element element) {
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
def.setSource(context.extractSource(element));
|
||||
context.registerBeanComponent(new BeanComponentDefinition(def, id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied code of SpringConfiguredBeanDefinitionParser until this class gets public.
|
||||
*
|
||||
* @see http://jira.springframework.org/browse/SPR-7340
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
private static class SpringConfiguredBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private void registerInfrastructureBeanWithId(AbstractBeanDefinition def,
|
||||
String id, ParserContext context, Element element) {
|
||||
/**
|
||||
* The bean name of the internally managed bean configurer aspect.
|
||||
*/
|
||||
private static final String BEAN_CONFIGURER_ASPECT_BEAN_NAME = "org.springframework.context.config.internalBeanConfigurerAspect";
|
||||
|
||||
def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
def.setSource(context.extractSource(element));
|
||||
context.registerBeanComponent(new BeanComponentDefinition(def, id));
|
||||
}
|
||||
private static final String BEAN_CONFIGURER_ASPECT_CLASS_NAME = "org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect";
|
||||
|
||||
/**
|
||||
* Copied code of SpringConfiguredBeanDefinitionParser until this class gets
|
||||
* public.
|
||||
*
|
||||
* @see http://jira.springframework.org/browse/SPR-7340
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
private static class SpringConfiguredBeanDefinitionParser implements
|
||||
BeanDefinitionParser {
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
|
||||
/**
|
||||
* The bean name of the internally managed bean configurer aspect.
|
||||
*/
|
||||
private static final String BEAN_CONFIGURER_ASPECT_BEAN_NAME =
|
||||
"org.springframework.context.config.internalBeanConfigurerAspect";
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(BEAN_CONFIGURER_ASPECT_BEAN_NAME)) {
|
||||
RootBeanDefinition def = new RootBeanDefinition();
|
||||
def.setBeanClassName(BEAN_CONFIGURER_ASPECT_CLASS_NAME);
|
||||
def.setFactoryMethodName("aspectOf");
|
||||
|
||||
private static final String BEAN_CONFIGURER_ASPECT_CLASS_NAME =
|
||||
"org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect";
|
||||
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(
|
||||
BEAN_CONFIGURER_ASPECT_BEAN_NAME)) {
|
||||
RootBeanDefinition def = new RootBeanDefinition();
|
||||
def.setBeanClassName(BEAN_CONFIGURER_ASPECT_CLASS_NAME);
|
||||
def.setFactoryMethodName("aspectOf");
|
||||
|
||||
def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
def.setSource(parserContext.extractSource(element));
|
||||
parserContext
|
||||
.registerBeanComponent(new BeanComponentDefinition(def,
|
||||
BEAN_CONFIGURER_ASPECT_BEAN_NAME));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
def.setSource(parserContext.extractSource(element));
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(def, BEAN_CONFIGURER_ASPECT_BEAN_NAME));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,132 +26,106 @@ import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcesso
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/**
|
||||
* Parser to create bean definitions for repositories namespace. Registers bean
|
||||
* definitions for repositories as well as
|
||||
* {@code PersistenceAnnotationBeanPostProcessor} and
|
||||
* {@code PersistenceExceptionTranslationPostProcessor} to transparently inject
|
||||
* entity manager factory instance and apply exception translation.
|
||||
* Parser to create bean definitions for repositories namespace. Registers bean definitions for repositories as well as
|
||||
* {@code PersistenceAnnotationBeanPostProcessor} and {@code PersistenceExceptionTranslationPostProcessor} to
|
||||
* transparently inject entity manager factory instance and apply exception translation.
|
||||
* <p>
|
||||
* The definition parser allows two ways of configuration. Either it looks up
|
||||
* the manually defined repository instances or scans the defined domain package
|
||||
* for candidates for repositories.
|
||||
* The definition parser allows two ways of configuration. Either it looks up the manually defined repository instances
|
||||
* or scans the defined domain package for candidates for repositories.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Eberhard Wolff
|
||||
* @author Gil Markham
|
||||
*/
|
||||
class JpaRepositoryConfigDefinitionParser
|
||||
extends
|
||||
AbstractRepositoryConfigDefinitionParser<SimpleJpaRepositoryConfiguration, JpaRepositoryConfiguration> {
|
||||
class JpaRepositoryConfigDefinitionParser extends
|
||||
AbstractRepositoryConfigDefinitionParser<SimpleJpaRepositoryConfiguration, JpaRepositoryConfiguration> {
|
||||
|
||||
private static final Class<?> PAB_POST_PROCESSOR =
|
||||
PersistenceAnnotationBeanPostProcessor.class;
|
||||
private static final Class<?> PET_POST_PROCESSOR =
|
||||
PersistenceExceptionTranslationPostProcessor.class;
|
||||
private static final Class<?> PAB_POST_PROCESSOR = PersistenceAnnotationBeanPostProcessor.class;
|
||||
private static final Class<?> PET_POST_PROCESSOR = PersistenceExceptionTranslationPostProcessor.class;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.config.
|
||||
* AbstractRepositoryConfigDefinitionParser
|
||||
* #getGlobalRepositoryConfigInformation(org.w3c.dom.Element)
|
||||
*/
|
||||
@Override
|
||||
protected SimpleJpaRepositoryConfiguration getGlobalRepositoryConfigInformation(Element element) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.config.
|
||||
* AbstractRepositoryConfigDefinitionParser
|
||||
* #getGlobalRepositoryConfigInformation(org.w3c.dom.Element)
|
||||
*/
|
||||
@Override
|
||||
protected SimpleJpaRepositoryConfiguration getGlobalRepositoryConfigInformation(
|
||||
Element element) {
|
||||
return new SimpleJpaRepositoryConfiguration(element);
|
||||
}
|
||||
|
||||
return new SimpleJpaRepositoryConfiguration(element);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.config.
|
||||
* AbstractRepositoryConfigDefinitionParser
|
||||
* #postProcessBeanDefinition(org.springframework
|
||||
* .data.repository.config.SingleRepositoryConfigInformation,
|
||||
* org.springframework.beans.factory.support.BeanDefinitionBuilder,
|
||||
* org.springframework.beans.factory.support.BeanDefinitionRegistry,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessBeanDefinition(JpaRepositoryConfiguration ctx, BeanDefinitionBuilder builder,
|
||||
BeanDefinitionRegistry registry, Object beanSource) {
|
||||
|
||||
String entityManagerRef = ctx.getEntityManagerFactoryRef();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.config.
|
||||
* AbstractRepositoryConfigDefinitionParser
|
||||
* #postProcessBeanDefinition(org.springframework
|
||||
* .data.repository.config.SingleRepositoryConfigInformation,
|
||||
* org.springframework.beans.factory.support.BeanDefinitionBuilder,
|
||||
* org.springframework.beans.factory.support.BeanDefinitionRegistry,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessBeanDefinition(JpaRepositoryConfiguration ctx,
|
||||
BeanDefinitionBuilder builder, BeanDefinitionRegistry registry,
|
||||
Object beanSource) {
|
||||
if (StringUtils.hasText(entityManagerRef)) {
|
||||
builder.addPropertyValue("entityManager", getEntityManagerBeanDefinitionFor(entityManagerRef, beanSource));
|
||||
}
|
||||
}
|
||||
|
||||
String entityManagerRef = ctx.getEntityManagerFactoryRef();
|
||||
/**
|
||||
* Creates an anonymous factory to extract the actual {@link javax.persistence.EntityManager} from the
|
||||
* {@link javax.persistence.EntityManagerFactory} bean name reference.
|
||||
*
|
||||
* @param entityManagerFactoryBeanName
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinition getEntityManagerBeanDefinitionFor(String entityManagerFactoryBeanName, Object source) {
|
||||
|
||||
if (StringUtils.hasText(entityManagerRef)) {
|
||||
builder.addPropertyValue(
|
||||
"entityManager",
|
||||
getEntityManagerBeanDefinitionFor(entityManagerRef,
|
||||
beanSource));
|
||||
}
|
||||
}
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator");
|
||||
builder.setFactoryMethod("createSharedEntityManager");
|
||||
builder.addConstructorArgReference(entityManagerFactoryBeanName);
|
||||
|
||||
AbstractBeanDefinition bean = builder.getRawBeanDefinition();
|
||||
bean.setSource(source);
|
||||
|
||||
/**
|
||||
* Creates an anonymous factory to extract the actual
|
||||
* {@link javax.persistence.EntityManager} from the
|
||||
* {@link javax.persistence.EntityManagerFactory} bean name reference.
|
||||
*
|
||||
* @param entityManagerFactoryBeanName
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinition getEntityManagerBeanDefinitionFor(
|
||||
String entityManagerFactoryBeanName, Object source) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator");
|
||||
builder.setFactoryMethod("createSharedEntityManager");
|
||||
builder.addConstructorArgReference(entityManagerFactoryBeanName);
|
||||
/**
|
||||
* Registers an additional {@link org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor} to
|
||||
* trigger automatic injextion of {@link javax.persistence.EntityManager} .
|
||||
*
|
||||
* @param registry
|
||||
* @param source
|
||||
*/
|
||||
@Override
|
||||
protected void registerBeansForRoot(BeanDefinitionRegistry registry, Object source) {
|
||||
|
||||
AbstractBeanDefinition bean = builder.getRawBeanDefinition();
|
||||
bean.setSource(source);
|
||||
super.registerBeansForRoot(registry, source);
|
||||
|
||||
return bean;
|
||||
}
|
||||
if (!hasBean(PET_POST_PROCESSOR, registry)) {
|
||||
|
||||
AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(PET_POST_PROCESSOR)
|
||||
.getBeanDefinition();
|
||||
|
||||
/**
|
||||
* Registers an additional
|
||||
* {@link org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor}
|
||||
* to trigger automatic injextion of {@link javax.persistence.EntityManager}
|
||||
* .
|
||||
*
|
||||
* @param registry
|
||||
* @param source
|
||||
*/
|
||||
@Override
|
||||
protected void registerBeansForRoot(BeanDefinitionRegistry registry,
|
||||
Object source) {
|
||||
registerWithSourceAndGeneratedBeanName(registry, definition, source);
|
||||
}
|
||||
|
||||
super.registerBeansForRoot(registry, source);
|
||||
if (!hasBean(PAB_POST_PROCESSOR, registry)) {
|
||||
|
||||
if (!hasBean(PET_POST_PROCESSOR, registry)) {
|
||||
AbstractBeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(PAB_POST_PROCESSOR)
|
||||
.getBeanDefinition();
|
||||
|
||||
AbstractBeanDefinition definition =
|
||||
BeanDefinitionBuilder
|
||||
.rootBeanDefinition(PET_POST_PROCESSOR)
|
||||
.getBeanDefinition();
|
||||
|
||||
registerWithSourceAndGeneratedBeanName(registry, definition, source);
|
||||
}
|
||||
|
||||
if (!hasBean(PAB_POST_PROCESSOR, registry)) {
|
||||
|
||||
AbstractBeanDefinition definition =
|
||||
BeanDefinitionBuilder
|
||||
.rootBeanDefinition(PAB_POST_PROCESSOR)
|
||||
.getBeanDefinition();
|
||||
|
||||
registerWithSourceAndGeneratedBeanName(registry, definition, source);
|
||||
}
|
||||
}
|
||||
registerWithSourceAndGeneratedBeanName(registry, definition, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
|
||||
/**
|
||||
* Simple namespace handler for {@literal repositories} namespace.
|
||||
*
|
||||
@@ -25,16 +24,14 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
*/
|
||||
public class JpaRepositoryNameSpaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
|
||||
*/
|
||||
public void init() {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
|
||||
*/
|
||||
public void init() {
|
||||
|
||||
registerBeanDefinitionParser("repositories",
|
||||
new JpaRepositoryConfigDefinitionParser());
|
||||
registerBeanDefinitionParser("auditing",
|
||||
new AuditingBeanDefinitionParser());
|
||||
}
|
||||
registerBeanDefinitionParser("repositories", new JpaRepositoryConfigDefinitionParser());
|
||||
registerBeanDefinitionParser("auditing", new AuditingBeanDefinitionParser());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,134 +21,116 @@ import org.springframework.data.repository.config.RepositoryConfig;
|
||||
import org.springframework.data.repository.config.SingleRepositoryConfigInformation;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SimpleJpaRepositoryConfiguration
|
||||
extends
|
||||
RepositoryConfig<SimpleJpaRepositoryConfiguration.JpaRepositoryConfiguration, SimpleJpaRepositoryConfiguration> {
|
||||
public class SimpleJpaRepositoryConfiguration extends
|
||||
RepositoryConfig<SimpleJpaRepositoryConfiguration.JpaRepositoryConfiguration, SimpleJpaRepositoryConfiguration> {
|
||||
|
||||
private static final String FACTORY_CLASS =
|
||||
"org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean";
|
||||
private static final String ENTITY_MANAGER_FACTORY_REF =
|
||||
"entity-manager-factory-ref";
|
||||
private static final String FACTORY_CLASS = "org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean";
|
||||
private static final String ENTITY_MANAGER_FACTORY_REF = "entity-manager-factory-ref";
|
||||
|
||||
/**
|
||||
* @param repositoriesElement
|
||||
*/
|
||||
public SimpleJpaRepositoryConfiguration(Element repositoriesElement) {
|
||||
|
||||
/**
|
||||
* @param repositoriesElement
|
||||
*/
|
||||
public SimpleJpaRepositoryConfiguration(Element repositoriesElement) {
|
||||
super(repositoriesElement, FACTORY_CLASS);
|
||||
}
|
||||
|
||||
super(repositoriesElement, FACTORY_CLASS);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
|
||||
* #getAutoconfigRepositoryInformation(java.lang.String)
|
||||
*/
|
||||
public JpaRepositoryConfiguration getAutoconfigRepositoryInformation(String interfaceName) {
|
||||
|
||||
return new AutomaticJpaRepositoryConfigInformation(interfaceName, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
|
||||
* #getAutoconfigRepositoryInformation(java.lang.String)
|
||||
*/
|
||||
public JpaRepositoryConfiguration getAutoconfigRepositoryInformation(
|
||||
String interfaceName) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.config.RepositoryConfigContext
|
||||
* #getManualRepositoryInformation(org.w3c.dom.Element,
|
||||
* org.springframework.data
|
||||
* .jpa.repository.config.CommonRepositoryInformation)
|
||||
*/
|
||||
@Override
|
||||
public JpaRepositoryConfiguration createSingleRepositoryConfigInformationFor(Element element) {
|
||||
|
||||
return new AutomaticJpaRepositoryConfigInformation(interfaceName, this);
|
||||
}
|
||||
return new ManualJpaRepositoryConfigInformation(element, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.config.CommonRepositoryConfigInformation
|
||||
* #getNamedQueriesLocation()
|
||||
*/
|
||||
public String getNamedQueriesLocation() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.config.RepositoryConfigContext
|
||||
* #getManualRepositoryInformation(org.w3c.dom.Element,
|
||||
* org.springframework.data
|
||||
* .jpa.repository.config.CommonRepositoryInformation)
|
||||
*/
|
||||
@Override
|
||||
public JpaRepositoryConfiguration createSingleRepositoryConfigInformationFor(
|
||||
Element element) {
|
||||
return "classpath*:META-INF/jpa-named-queries.properties";
|
||||
}
|
||||
|
||||
return new ManualJpaRepositoryConfigInformation(element, this);
|
||||
}
|
||||
/**
|
||||
* Returns the name of the entity manager factory bean.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getEntityManagerFactoryRef() {
|
||||
|
||||
return getSource().getAttribute(ENTITY_MANAGER_FACTORY_REF);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.config.CommonRepositoryConfigInformation
|
||||
* #getNamedQueriesLocation()
|
||||
*/
|
||||
public String getNamedQueriesLocation() {
|
||||
private static class AutomaticJpaRepositoryConfigInformation extends
|
||||
AutomaticRepositoryConfigInformation<SimpleJpaRepositoryConfiguration> implements JpaRepositoryConfiguration {
|
||||
|
||||
return "classpath*:META-INF/jpa-named-queries.properties";
|
||||
}
|
||||
public AutomaticJpaRepositoryConfigInformation(String interfaceName, SimpleJpaRepositoryConfiguration parent) {
|
||||
|
||||
super(interfaceName, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the entity manager factory bean.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getEntityManagerFactoryRef() {
|
||||
/**
|
||||
* Returns the {@link javax.persistence.EntityManagerFactory} reference to be used for all the repository instances
|
||||
* configured.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getEntityManagerFactoryRef() {
|
||||
|
||||
return getSource().getAttribute(ENTITY_MANAGER_FACTORY_REF);
|
||||
}
|
||||
return getParent().getEntityManagerFactoryRef();
|
||||
}
|
||||
}
|
||||
|
||||
private static class AutomaticJpaRepositoryConfigInformation
|
||||
extends
|
||||
AutomaticRepositoryConfigInformation<SimpleJpaRepositoryConfiguration>
|
||||
implements JpaRepositoryConfiguration {
|
||||
private static class ManualJpaRepositoryConfigInformation extends
|
||||
ManualRepositoryConfigInformation<SimpleJpaRepositoryConfiguration> implements JpaRepositoryConfiguration {
|
||||
|
||||
public AutomaticJpaRepositoryConfigInformation(String interfaceName,
|
||||
SimpleJpaRepositoryConfiguration parent) {
|
||||
public ManualJpaRepositoryConfigInformation(Element element, SimpleJpaRepositoryConfiguration parent) {
|
||||
|
||||
super(interfaceName, parent);
|
||||
}
|
||||
super(element, parent);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.config.
|
||||
* SimpleJpaRepositoryConfiguration
|
||||
* .JpaRepositoryConfiguration#getEntityManagerFactoryRef()
|
||||
*/
|
||||
public String getEntityManagerFactoryRef() {
|
||||
|
||||
/**
|
||||
* Returns the {@link javax.persistence.EntityManagerFactory} reference
|
||||
* to be used for all the repository instances configured.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getEntityManagerFactoryRef() {
|
||||
return getAttribute(ENTITY_MANAGER_FACTORY_REF);
|
||||
}
|
||||
}
|
||||
|
||||
return getParent().getEntityManagerFactoryRef();
|
||||
}
|
||||
}
|
||||
static interface JpaRepositoryConfiguration extends
|
||||
SingleRepositoryConfigInformation<SimpleJpaRepositoryConfiguration> {
|
||||
|
||||
private static class ManualJpaRepositoryConfigInformation extends
|
||||
ManualRepositoryConfigInformation<SimpleJpaRepositoryConfiguration>
|
||||
implements JpaRepositoryConfiguration {
|
||||
|
||||
public ManualJpaRepositoryConfigInformation(Element element,
|
||||
SimpleJpaRepositoryConfiguration parent) {
|
||||
|
||||
super(element, parent);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.config.
|
||||
* SimpleJpaRepositoryConfiguration
|
||||
* .JpaRepositoryConfiguration#getEntityManagerFactoryRef()
|
||||
*/
|
||||
public String getEntityManagerFactoryRef() {
|
||||
|
||||
return getAttribute(ENTITY_MANAGER_FACTORY_REF);
|
||||
}
|
||||
}
|
||||
|
||||
static interface JpaRepositoryConfiguration extends
|
||||
SingleRepositoryConfigInformation<SimpleJpaRepositoryConfiguration> {
|
||||
|
||||
String getEntityManagerFactoryRef();
|
||||
}
|
||||
String getEntityManagerFactoryRef();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class to implement {@link RepositoryQuery}s.
|
||||
*
|
||||
@@ -34,98 +33,87 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public abstract class AbstractJpaQuery implements RepositoryQuery {
|
||||
|
||||
private final JpaQueryMethod method;
|
||||
private final EntityManager em;
|
||||
private final JpaQueryMethod method;
|
||||
private final EntityManager em;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractJpaQuery} from the given {@link JpaQueryMethod}.
|
||||
*
|
||||
* @param method
|
||||
* @param em
|
||||
*/
|
||||
public AbstractJpaQuery(JpaQueryMethod method, EntityManager em) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractJpaQuery} from the given
|
||||
* {@link JpaQueryMethod}.
|
||||
*
|
||||
* @param method
|
||||
* @param em
|
||||
*/
|
||||
public AbstractJpaQuery(JpaQueryMethod method, EntityManager em) {
|
||||
Assert.notNull(method);
|
||||
Assert.notNull(em);
|
||||
|
||||
Assert.notNull(method);
|
||||
Assert.notNull(em);
|
||||
this.method = method;
|
||||
this.em = em;
|
||||
}
|
||||
|
||||
this.method = method;
|
||||
this.em = em;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.RepositoryQuery#getQueryMethod
|
||||
* ()
|
||||
*/
|
||||
public QueryMethod getQueryMethod() {
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.RepositoryQuery#getQueryMethod
|
||||
* ()
|
||||
*/
|
||||
public QueryMethod getQueryMethod() {
|
||||
/**
|
||||
* @return the em
|
||||
*/
|
||||
protected EntityManager getEntityManager() {
|
||||
|
||||
return method;
|
||||
}
|
||||
return em;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.RepositoryQuery#execute(java
|
||||
* .lang.Object[])
|
||||
*/
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
/**
|
||||
* @return the em
|
||||
*/
|
||||
protected EntityManager getEntityManager() {
|
||||
return doExecute(getExecution(), parameters);
|
||||
}
|
||||
|
||||
return em;
|
||||
}
|
||||
/**
|
||||
* @param execution
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
private Object doExecute(JpaQueryExecution execution, Object[] values) {
|
||||
|
||||
return execution.execute(this, values);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.RepositoryQuery#execute(java
|
||||
* .lang.Object[])
|
||||
*/
|
||||
public Object execute(Object[] parameters) {
|
||||
protected JpaQueryExecution getExecution() {
|
||||
|
||||
return doExecute(getExecution(), parameters);
|
||||
}
|
||||
switch (method.getType()) {
|
||||
|
||||
case COLLECTION:
|
||||
return new CollectionExecution();
|
||||
case PAGING:
|
||||
return new PagedExecution(method.getParameters());
|
||||
case MODIFYING:
|
||||
return method.getClearAutomatically() ? new ModifyingExecution(method, em) : new ModifyingExecution(method, null);
|
||||
default:
|
||||
return new SingleEntityExecution();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param execution
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
private Object doExecute(JpaQueryExecution execution, Object[] values) {
|
||||
protected ParameterBinder createBinder(Object[] values) {
|
||||
|
||||
return execution.execute(this, values);
|
||||
}
|
||||
return new ParameterBinder(getQueryMethod().getParameters(), values);
|
||||
}
|
||||
|
||||
protected abstract Query createQuery(Object[] values);
|
||||
|
||||
protected JpaQueryExecution getExecution() {
|
||||
|
||||
switch (method.getType()) {
|
||||
|
||||
case COLLECTION:
|
||||
return new CollectionExecution();
|
||||
case PAGING:
|
||||
return new PagedExecution(method.getParameters());
|
||||
case MODIFYING:
|
||||
return method.getClearAutomatically() ? new ModifyingExecution(
|
||||
method, em) : new ModifyingExecution(method, null);
|
||||
default:
|
||||
return new SingleEntityExecution();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected ParameterBinder createBinder(Object[] values) {
|
||||
|
||||
return new ParameterBinder(getQueryMethod().getParameters(), values);
|
||||
}
|
||||
|
||||
|
||||
protected abstract Query createQuery(Object[] values);
|
||||
|
||||
|
||||
protected abstract Query createCountQuery(Object[] values);
|
||||
protected abstract Query createCountQuery(Object[] values);
|
||||
}
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
|
||||
/**
|
||||
* Base class for {@link String} based JPA queries.
|
||||
*
|
||||
@@ -25,15 +24,15 @@ import javax.persistence.EntityManager;
|
||||
*/
|
||||
public abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractStringBasedJpaQuery}.
|
||||
*
|
||||
* @param method
|
||||
* @param em
|
||||
*/
|
||||
public AbstractStringBasedJpaQuery(JpaQueryMethod method, EntityManager em) {
|
||||
/**
|
||||
* Creates a new {@link AbstractStringBasedJpaQuery}.
|
||||
*
|
||||
* @param method
|
||||
* @param em
|
||||
*/
|
||||
public AbstractStringBasedJpaQuery(JpaQueryMethod method, EntityManager em) {
|
||||
|
||||
super(method, em);
|
||||
}
|
||||
super(method, em);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,80 +29,68 @@ import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Special {@link ParameterBinder} that uses {@link ParameterExpression}s to
|
||||
* bind query parameters.
|
||||
* Special {@link ParameterBinder} that uses {@link ParameterExpression}s to bind query parameters.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class CriteriaQueryParameterBinder extends ParameterBinder {
|
||||
|
||||
private final Iterator<ParameterExpression<?>> expressions;
|
||||
private final Iterator<ParameterExpression<?>> expressions;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CriteriaQueryParameterBinder} for the given {@link Parameters}, values and some
|
||||
* {@link ParameterExpression}.
|
||||
*
|
||||
* @param parameters
|
||||
*/
|
||||
CriteriaQueryParameterBinder(Parameters parameters, Object[] values, Iterable<ParameterExpression<?>> expressions) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link CriteriaQueryParameterBinder} for the given
|
||||
* {@link Parameters}, values and some {@link ParameterExpression}.
|
||||
*
|
||||
* @param parameters
|
||||
*/
|
||||
CriteriaQueryParameterBinder(Parameters parameters, Object[] values,
|
||||
Iterable<ParameterExpression<?>> expressions) {
|
||||
super(parameters, values);
|
||||
Assert.notNull(expressions);
|
||||
this.expressions = expressions.iterator();
|
||||
}
|
||||
|
||||
super(parameters, values);
|
||||
Assert.notNull(expressions);
|
||||
this.expressions = expressions.iterator();
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.ParameterBinder#bind(javax
|
||||
* .persistence.Query, org.springframework.data.repository.query.Parameter,
|
||||
* java.lang.Object, int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void bind(Query query, Parameter parameter, Object value, int position) {
|
||||
|
||||
ParameterExpression<Object> expression = (ParameterExpression<Object>) expressions.next();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.ParameterBinder#bind(javax
|
||||
* .persistence.Query, org.springframework.data.repository.query.Parameter,
|
||||
* java.lang.Object, int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void bind(Query query, Parameter parameter, Object value,
|
||||
int position) {
|
||||
Object valueToBind = Collection.class.equals(expression.getJavaType()) ? toCollection(value) : value;
|
||||
|
||||
ParameterExpression<Object> expression =
|
||||
(ParameterExpression<Object>) expressions.next();
|
||||
query.setParameter(expression, valueToBind);
|
||||
}
|
||||
|
||||
Object valueToBind =
|
||||
Collection.class.equals(expression.getJavaType()) ? toCollection(value)
|
||||
: value;
|
||||
/**
|
||||
* Return sthe given argument as {@link Collection} which means it will return it as is if it's a {@link Collections},
|
||||
* turn an array into an {@link ArrayList} or simply wrap any other value into a single element {@link Collections}.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
private static Collection<?> toCollection(Object value) {
|
||||
|
||||
query.setParameter(expression, valueToBind);
|
||||
}
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value instanceof Collection) {
|
||||
return (Collection<?>) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return sthe given argument as {@link Collection} which means it will
|
||||
* return it as is if it's a {@link Collections}, turn an array into an
|
||||
* {@link ArrayList} or simply wrap any other value into a single element
|
||||
* {@link Collections}.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
private static Collection<?> toCollection(Object value) {
|
||||
if (ObjectUtils.isArray(value)) {
|
||||
return Arrays.asList(ObjectUtils.toObjectArray(value));
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value instanceof Collection) {
|
||||
return (Collection<?>) value;
|
||||
}
|
||||
|
||||
if (ObjectUtils.isArray(value)) {
|
||||
return Arrays.asList(ObjectUtils.toObjectArray(value));
|
||||
}
|
||||
|
||||
return Collections.singleton(value);
|
||||
}
|
||||
return Collections.singleton(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
|
||||
/**
|
||||
* Special {@link JpaQueryCreator} that creates a count projecting query.
|
||||
*
|
||||
@@ -33,36 +32,34 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
*/
|
||||
public class JpaCountQueryCreator extends JpaQueryCreator {
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaCountQueryCreator}.
|
||||
*
|
||||
* @param tree
|
||||
* @param domainClass
|
||||
* @param parameters
|
||||
* @param em
|
||||
*/
|
||||
public JpaCountQueryCreator(PartTree tree, Class<?> domainClass,
|
||||
Parameters parameters, EntityManager em) {
|
||||
/**
|
||||
* Creates a new {@link JpaCountQueryCreator}.
|
||||
*
|
||||
* @param tree
|
||||
* @param domainClass
|
||||
* @param parameters
|
||||
* @param em
|
||||
*/
|
||||
public JpaCountQueryCreator(PartTree tree, Class<?> domainClass, Parameters parameters, EntityManager em) {
|
||||
|
||||
super(tree, domainClass, parameters, em);
|
||||
}
|
||||
super(tree, domainClass, parameters, em);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.JpaQueryCreator#complete
|
||||
* (javax.persistence.criteria.Predicate,
|
||||
* org.springframework.data.domain.Sort,
|
||||
* javax.persistence.criteria.CriteriaQuery,
|
||||
* javax.persistence.criteria.CriteriaBuilder,
|
||||
* javax.persistence.criteria.Root)
|
||||
*/
|
||||
@Override
|
||||
protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort, CriteriaQuery<Object> query,
|
||||
CriteriaBuilder builder, Root<?> root) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.JpaQueryCreator#complete
|
||||
* (javax.persistence.criteria.Predicate,
|
||||
* org.springframework.data.domain.Sort,
|
||||
* javax.persistence.criteria.CriteriaQuery,
|
||||
* javax.persistence.criteria.CriteriaBuilder,
|
||||
* javax.persistence.criteria.Root)
|
||||
*/
|
||||
@Override
|
||||
protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort,
|
||||
CriteriaQuery<Object> query, CriteriaBuilder builder, Root<?> root) {
|
||||
|
||||
return query.select(builder.count(root)).where(predicate);
|
||||
}
|
||||
return query.select(builder.count(root)).where(predicate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,315 +41,269 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.data.repository.query.parser.Property;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Query creator to create a {@link CriteriaQuery} from a {@link PartTree}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JpaQueryCreator extends
|
||||
AbstractQueryCreator<CriteriaQuery<Object>, Predicate> {
|
||||
public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>, Predicate> {
|
||||
|
||||
private final CriteriaBuilder builder;
|
||||
private final Root<?> root;
|
||||
private final CriteriaQuery<Object> query;
|
||||
private final ParameterExpressionProvider provider;
|
||||
private final CriteriaBuilder builder;
|
||||
private final Root<?> root;
|
||||
private final CriteriaQuery<Object> query;
|
||||
private final ParameterExpressionProvider provider;
|
||||
|
||||
/**
|
||||
* Create a new {@link JpaQueryCreator}.
|
||||
*
|
||||
* @param tree
|
||||
* @param domainClass
|
||||
* @param accessor
|
||||
* @param em
|
||||
*/
|
||||
public JpaQueryCreator(PartTree tree, Class<?> domainClass, Parameters parameters, EntityManager em) {
|
||||
|
||||
/**
|
||||
* Create a new {@link JpaQueryCreator}.
|
||||
*
|
||||
* @param tree
|
||||
* @param domainClass
|
||||
* @param accessor
|
||||
* @param em
|
||||
*/
|
||||
public JpaQueryCreator(PartTree tree, Class<?> domainClass,
|
||||
Parameters parameters, EntityManager em) {
|
||||
super(tree);
|
||||
|
||||
super(tree);
|
||||
this.builder = em.getCriteriaBuilder();
|
||||
this.query = builder.createQuery().distinct(tree.isDistinct());
|
||||
this.root = query.from(domainClass);
|
||||
this.provider = new ParameterExpressionProvider(builder, parameters.getBindableParameters());
|
||||
}
|
||||
|
||||
this.builder = em.getCriteriaBuilder();
|
||||
this.query = builder.createQuery().distinct(tree.isDistinct());
|
||||
this.root = query.from(domainClass);
|
||||
this.provider =
|
||||
new ParameterExpressionProvider(builder,
|
||||
parameters.getBindableParameters());
|
||||
}
|
||||
/**
|
||||
* Returns all {@link ParameterExpression} created when creating the query.
|
||||
*
|
||||
* @return the parameterExpressions
|
||||
*/
|
||||
public List<ParameterExpression<?>> getParameterExpressions() {
|
||||
|
||||
return provider.getExpressions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link ParameterExpression} created when creating the query.
|
||||
*
|
||||
* @return the parameterExpressions
|
||||
*/
|
||||
public List<ParameterExpression<?>> getParameterExpressions() {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.parser.AbstractQueryCreator
|
||||
* #create(org.springframework.data.repository.query.parser.Part,
|
||||
* java.util.Iterator)
|
||||
*/
|
||||
@Override
|
||||
protected Predicate create(Part part, Iterator<Object> iterator) {
|
||||
|
||||
return provider.getExpressions();
|
||||
}
|
||||
return toPredicate(part, root);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.parser.AbstractQueryCreator
|
||||
* #and(org.springframework.data.repository.query.parser.Part,
|
||||
* java.lang.Object, java.util.Iterator)
|
||||
*/
|
||||
@Override
|
||||
protected Predicate and(Part part, Predicate base, Iterator<Object> iterator) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.parser.AbstractQueryCreator
|
||||
* #create(org.springframework.data.repository.query.parser.Part,
|
||||
* java.util.Iterator)
|
||||
*/
|
||||
@Override
|
||||
protected Predicate create(Part part, Iterator<Object> iterator) {
|
||||
return builder.and(base, toPredicate(part, root));
|
||||
}
|
||||
|
||||
return toPredicate(part, root);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.parser.AbstractQueryCreator
|
||||
* #or(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Predicate or(Predicate base, Predicate predicate) {
|
||||
|
||||
return builder.or(base, predicate);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.parser.AbstractQueryCreator
|
||||
* #and(org.springframework.data.repository.query.parser.Part,
|
||||
* java.lang.Object, java.util.Iterator)
|
||||
*/
|
||||
@Override
|
||||
protected Predicate and(Part part, Predicate base, Iterator<Object> iterator) {
|
||||
/**
|
||||
* Finalizes the given {@link Predicate} and applies the given sort. Delegates to
|
||||
* {@link #complete(Predicate, Sort, CriteriaQuery, CriteriaBuilder)} and hands it the current {@link CriteriaQuery}
|
||||
* and {@link CriteriaBuilder}.
|
||||
*/
|
||||
@Override
|
||||
protected final CriteriaQuery<Object> complete(Predicate predicate, Sort sort) {
|
||||
|
||||
return builder.and(base, toPredicate(part, root));
|
||||
}
|
||||
return complete(predicate, sort, query, builder, root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method to finalize the given {@link Predicate} using the given {@link CriteriaQuery} and
|
||||
* {@link CriteriaBuilder}.
|
||||
*
|
||||
* @param predicate
|
||||
* @param sort
|
||||
* @param query
|
||||
* @param builder
|
||||
* @return
|
||||
*/
|
||||
protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort, CriteriaQuery<Object> query,
|
||||
CriteriaBuilder builder, Root<?> root) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.query.parser.AbstractQueryCreator
|
||||
* #or(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Predicate or(Predicate base, Predicate predicate) {
|
||||
return this.query.select(root).where(predicate).orderBy(QueryUtils.toOrders(sort, root, builder));
|
||||
}
|
||||
|
||||
return builder.or(base, predicate);
|
||||
}
|
||||
/**
|
||||
* Creates a {@link Predicate} from the given {@link Part}.
|
||||
*
|
||||
* @param part
|
||||
* @param root
|
||||
* @param iterator
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private Predicate toPredicate(Part part, Root<?> root) {
|
||||
|
||||
Property property = part.getProperty();
|
||||
Expression<Object> path = toExpressionRecursively(root, property);
|
||||
|
||||
/**
|
||||
* Finalizes the given {@link Predicate} and applies the given sort.
|
||||
* Delegates to
|
||||
* {@link #complete(Predicate, Sort, CriteriaQuery, CriteriaBuilder)} and
|
||||
* hands it the current {@link CriteriaQuery} and {@link CriteriaBuilder}.
|
||||
*/
|
||||
@Override
|
||||
protected final CriteriaQuery<Object> complete(Predicate predicate,
|
||||
Sort sort) {
|
||||
switch (part.getType()) {
|
||||
|
||||
return complete(predicate, sort, query, builder, root);
|
||||
}
|
||||
case BETWEEN:
|
||||
ParameterExpression<Comparable> first = provider.next();
|
||||
ParameterExpression<Comparable> second = provider.next();
|
||||
return builder.between(root.<Comparable> get(part.getProperty().toDotPath()), first, second);
|
||||
case GREATER_THAN:
|
||||
return builder.greaterThan(getComparablePath(root, part), provider.next(Comparable.class));
|
||||
case LESS_THAN:
|
||||
return builder.lessThan(getComparablePath(root, part), provider.next(Comparable.class));
|
||||
case IS_NULL:
|
||||
return path.isNull();
|
||||
case IS_NOT_NULL:
|
||||
return path.isNotNull();
|
||||
case NOT_IN:
|
||||
return path.in(provider.next(Collection.class)).not();
|
||||
case IN:
|
||||
return path.in(provider.next(Collection.class));
|
||||
case LIKE:
|
||||
return builder.like(root.<String> get(part.getProperty().toDotPath()), provider.next(String.class));
|
||||
case NOT_LIKE:
|
||||
return builder.like(root.<String> get(part.getProperty().toDotPath()), provider.next(String.class)).not();
|
||||
case SIMPLE_PROPERTY:
|
||||
return builder.equal(path, provider.next());
|
||||
case NEGATING_SIMPLE_PROPERTY:
|
||||
return builder.notEqual(path, provider.next());
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported keyword + " + part.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private Expression<Object> toExpressionRecursively(Path<Object> path, Property property) {
|
||||
|
||||
/**
|
||||
* Template method to finalize the given {@link Predicate} using the given
|
||||
* {@link CriteriaQuery} and {@link CriteriaBuilder}.
|
||||
*
|
||||
* @param predicate
|
||||
* @param sort
|
||||
* @param query
|
||||
* @param builder
|
||||
* @return
|
||||
*/
|
||||
protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort,
|
||||
CriteriaQuery<Object> query, CriteriaBuilder builder, Root<?> root) {
|
||||
Path<Object> result = path.get(property.getName());
|
||||
return property.hasNext() ? toExpressionRecursively(result, property.next()) : result;
|
||||
}
|
||||
|
||||
return this.query.select(root).where(predicate)
|
||||
.orderBy(QueryUtils.toOrders(sort, root, builder));
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Expression<T> toExpressionRecursively(From<?, ?> from, Property property) {
|
||||
|
||||
if (property.isCollection()) {
|
||||
Join<Object, Object> join = from.join(property.getName());
|
||||
return (Expression<T>) (property.hasNext() ? toExpressionRecursively((From<?, ?>) join, property.next()) : join);
|
||||
} else {
|
||||
Path<Object> path = from.get(property.getName());
|
||||
return (Expression<T>) (property.hasNext() ? toExpressionRecursively(path, property.next()) : path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Predicate} from the given {@link Part}.
|
||||
*
|
||||
* @param part
|
||||
* @param root
|
||||
* @param iterator
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private Predicate toPredicate(Part part, Root<?> root) {
|
||||
/**
|
||||
* Returns a path to a {@link Comparable}.
|
||||
*
|
||||
* @param root
|
||||
* @param part
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
private Expression<? extends Comparable> getComparablePath(Root<?> root, Part part) {
|
||||
|
||||
Property property = part.getProperty();
|
||||
Expression<Object> path = toExpressionRecursively(root, property);
|
||||
return toExpressionRecursively(root, part.getProperty());
|
||||
}
|
||||
|
||||
switch (part.getType()) {
|
||||
/**
|
||||
* Helper class to allow easy creation of {@link ParameterExpression}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ParameterExpressionProvider {
|
||||
|
||||
case BETWEEN:
|
||||
ParameterExpression<Comparable> first = provider.next();
|
||||
ParameterExpression<Comparable> second = provider.next();
|
||||
return builder.between(
|
||||
root.<Comparable> get(part.getProperty().toDotPath()),
|
||||
first, second);
|
||||
case GREATER_THAN:
|
||||
return builder.greaterThan(getComparablePath(root, part),
|
||||
provider.next(Comparable.class));
|
||||
case LESS_THAN:
|
||||
return builder.lessThan(getComparablePath(root, part),
|
||||
provider.next(Comparable.class));
|
||||
case IS_NULL:
|
||||
return path.isNull();
|
||||
case IS_NOT_NULL:
|
||||
return path.isNotNull();
|
||||
case NOT_IN:
|
||||
return path.in(provider.next(Collection.class)).not();
|
||||
case IN:
|
||||
return path.in(provider.next(Collection.class));
|
||||
case LIKE:
|
||||
return builder.like(
|
||||
root.<String> get(part.getProperty().toDotPath()),
|
||||
provider.next(String.class));
|
||||
case NOT_LIKE:
|
||||
return builder.like(
|
||||
root.<String> get(part.getProperty().toDotPath()),
|
||||
provider.next(String.class)).not();
|
||||
case SIMPLE_PROPERTY:
|
||||
return builder.equal(path, provider.next());
|
||||
case NEGATING_SIMPLE_PROPERTY:
|
||||
return builder.notEqual(path, provider.next());
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported keyword + "
|
||||
+ part.getType());
|
||||
}
|
||||
}
|
||||
private final CriteriaBuilder builder;
|
||||
private final Iterator<Parameter> parameters;
|
||||
private final List<ParameterExpression<?>> expressions;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ParameterExpressionProvider} from the given {@link CriteriaBuilder} and {@link Parameters}.
|
||||
*
|
||||
* @param builder
|
||||
* @param parameters
|
||||
*/
|
||||
public ParameterExpressionProvider(CriteriaBuilder builder, Parameters parameters) {
|
||||
|
||||
private Expression<Object> toExpressionRecursively(Path<Object> path,
|
||||
Property property) {
|
||||
Assert.notNull(builder);
|
||||
Assert.notNull(parameters);
|
||||
|
||||
Path<Object> result = path.get(property.getName());
|
||||
return property.hasNext() ? toExpressionRecursively(result,
|
||||
property.next()) : result;
|
||||
}
|
||||
this.builder = builder;
|
||||
this.parameters = parameters.iterator();
|
||||
this.expressions = new ArrayList<ParameterExpression<?>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link ParameterExpression}s built.
|
||||
*
|
||||
* @return the expressions
|
||||
*/
|
||||
public List<ParameterExpression<?>> getExpressions() {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Expression<T> toExpressionRecursively(From<?, ?> from,
|
||||
Property property) {
|
||||
return Collections.unmodifiableList(expressions);
|
||||
}
|
||||
|
||||
if (property.isCollection()) {
|
||||
Join<Object, Object> join = from.join(property.getName());
|
||||
return (Expression<T>) (property.hasNext() ? toExpressionRecursively(
|
||||
(From<?, ?>) join, property.next()) : join);
|
||||
} else {
|
||||
Path<Object> path = from.get(property.getName());
|
||||
return (Expression<T>) (property.hasNext() ? toExpressionRecursively(
|
||||
path, property.next()) : path);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Builds a new {@link ParameterExpression} for the next {@link Parameter}.
|
||||
*
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ParameterExpression<T> next() {
|
||||
|
||||
Parameter parameter = parameters.next();
|
||||
return (ParameterExpression<T>) next(parameter.getType(), parameter.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a path to a {@link Comparable}.
|
||||
*
|
||||
* @param root
|
||||
* @param part
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
private Expression<? extends Comparable> getComparablePath(Root<?> root,
|
||||
Part part) {
|
||||
/**
|
||||
* Builds a new {@link ParameterExpression} of the given type. Forwards the underlying {@link Parameters} as well.
|
||||
*
|
||||
* @param <T>
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public <T> ParameterExpression<T> next(Class<T> type) {
|
||||
|
||||
return toExpressionRecursively(root, part.getProperty());
|
||||
}
|
||||
parameters.next();
|
||||
return next(type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to allow easy creation of {@link ParameterExpression}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ParameterExpressionProvider {
|
||||
/**
|
||||
* Builds a new {@link ParameterExpression} for the given type and name.
|
||||
*
|
||||
* @param <T>
|
||||
* @param type must not be {@literal null}.
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> ParameterExpression<T> next(Class<T> type, String name) {
|
||||
|
||||
private final CriteriaBuilder builder;
|
||||
private final Iterator<Parameter> parameters;
|
||||
private final List<ParameterExpression<?>> expressions;
|
||||
Assert.notNull(type);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link ParameterExpressionProvider} from the given
|
||||
* {@link CriteriaBuilder} and {@link Parameters}.
|
||||
*
|
||||
* @param builder
|
||||
* @param parameters
|
||||
*/
|
||||
public ParameterExpressionProvider(CriteriaBuilder builder,
|
||||
Parameters parameters) {
|
||||
|
||||
Assert.notNull(builder);
|
||||
Assert.notNull(parameters);
|
||||
|
||||
this.builder = builder;
|
||||
this.parameters = parameters.iterator();
|
||||
this.expressions = new ArrayList<ParameterExpression<?>>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all {@link ParameterExpression}s built.
|
||||
*
|
||||
* @return the expressions
|
||||
*/
|
||||
public List<ParameterExpression<?>> getExpressions() {
|
||||
|
||||
return Collections.unmodifiableList(expressions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds a new {@link ParameterExpression} for the next
|
||||
* {@link Parameter}.
|
||||
*
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ParameterExpression<T> next() {
|
||||
|
||||
Parameter parameter = parameters.next();
|
||||
return (ParameterExpression<T>) next(parameter.getType(),
|
||||
parameter.getName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds a new {@link ParameterExpression} of the given type. Forwards
|
||||
* the underlying {@link Parameters} as well.
|
||||
*
|
||||
* @param <T>
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public <T> ParameterExpression<T> next(Class<T> type) {
|
||||
|
||||
parameters.next();
|
||||
return next(type, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds a new {@link ParameterExpression} for the given type and name.
|
||||
*
|
||||
* @param <T>
|
||||
* @param type must not be {@literal null}.
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> ParameterExpression<T> next(Class<T> type, String name) {
|
||||
|
||||
Assert.notNull(type);
|
||||
|
||||
ParameterExpression<?> expression =
|
||||
name == null ? builder.parameter(type) : builder.parameter(
|
||||
type, name);
|
||||
expressions.add(expression);
|
||||
return (ParameterExpression<T>) expression;
|
||||
}
|
||||
}
|
||||
ParameterExpression<?> expression = name == null ? builder.parameter(type) : builder.parameter(type, name);
|
||||
expressions.add(expression);
|
||||
return (ParameterExpression<T>) expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,150 +27,130 @@ import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Set of classes to contain query execution strategies. Depending (mostly) on
|
||||
* the return type of a {@link QueryMethod} a
|
||||
* {@link AbstractStringBasedJpaQuery} can be executed in various flavours.
|
||||
* Set of classes to contain query execution strategies. Depending (mostly) on the return type of a {@link QueryMethod}
|
||||
* a {@link AbstractStringBasedJpaQuery} can be executed in various flavours.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class JpaQueryExecution {
|
||||
|
||||
/**
|
||||
* Executes the given {@link AbstractStringBasedJpaQuery} with the given
|
||||
* {@link ParameterBinder}.
|
||||
*
|
||||
* @param query
|
||||
* @param binder
|
||||
* @return
|
||||
*/
|
||||
/**
|
||||
* Executes the given {@link AbstractStringBasedJpaQuery} with the given {@link ParameterBinder}.
|
||||
*
|
||||
* @param query
|
||||
* @param binder
|
||||
* @return
|
||||
*/
|
||||
|
||||
public Object execute(AbstractJpaQuery query, Object[] values) {
|
||||
public Object execute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
Assert.notNull(query);
|
||||
Assert.notNull(values);
|
||||
Assert.notNull(query);
|
||||
Assert.notNull(values);
|
||||
|
||||
try {
|
||||
return doExecute(query, values);
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return doExecute(query, values);
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to implement {@link AbstractStringBasedJpaQuery} executions by single enum values.
|
||||
*
|
||||
* @param query
|
||||
* @param binder
|
||||
* @return
|
||||
*/
|
||||
protected abstract Object doExecute(AbstractJpaQuery query, Object[] values);
|
||||
|
||||
/**
|
||||
* Method to implement {@link AbstractStringBasedJpaQuery} executions by
|
||||
* single enum values.
|
||||
*
|
||||
* @param query
|
||||
* @param binder
|
||||
* @return
|
||||
*/
|
||||
protected abstract Object doExecute(AbstractJpaQuery query, Object[] values);
|
||||
/**
|
||||
* Executes the {@link AbstractStringBasedJpaQuery} to return a simple collection of entities.
|
||||
*/
|
||||
static class CollectionExecution extends JpaQueryExecution {
|
||||
|
||||
/**
|
||||
* Executes the {@link AbstractStringBasedJpaQuery} to return a simple
|
||||
* collection of entities.
|
||||
*/
|
||||
static class CollectionExecution extends JpaQueryExecution {
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
return query.createQuery(values).getResultList();
|
||||
}
|
||||
}
|
||||
|
||||
return query.createQuery(values).getResultList();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Executes the {@link AbstractStringBasedJpaQuery} to return a {@link Page} of entities.
|
||||
*/
|
||||
static class PagedExecution extends JpaQueryExecution {
|
||||
|
||||
/**
|
||||
* Executes the {@link AbstractStringBasedJpaQuery} to return a {@link Page}
|
||||
* of entities.
|
||||
*/
|
||||
static class PagedExecution extends JpaQueryExecution {
|
||||
private final Parameters parameters;
|
||||
|
||||
private final Parameters parameters;
|
||||
public PagedExecution(Parameters parameters) {
|
||||
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public PagedExecution(Parameters parameters) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object doExecute(AbstractJpaQuery repositoryQuery, Object[] values) {
|
||||
|
||||
this.parameters = parameters;
|
||||
}
|
||||
// Execute query to compute total
|
||||
Query projection = repositoryQuery.createCountQuery(values);
|
||||
Long total = (Long) projection.getSingleResult();
|
||||
|
||||
Query query = repositoryQuery.createQuery(values);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object doExecute(AbstractJpaQuery repositoryQuery,
|
||||
Object[] values) {
|
||||
ParameterAccessor accessor = new ParametersParameterAccessor(parameters, values);
|
||||
|
||||
// Execute query to compute total
|
||||
Query projection = repositoryQuery.createCountQuery(values);
|
||||
Long total = (Long) projection.getSingleResult();
|
||||
return new PageImpl<Object>(query.getResultList(), accessor.getPageable(), total);
|
||||
}
|
||||
}
|
||||
|
||||
Query query = repositoryQuery.createQuery(values);
|
||||
/**
|
||||
* Executes a {@link AbstractStringBasedJpaQuery} to return a single entity.
|
||||
*/
|
||||
static class SingleEntityExecution extends JpaQueryExecution {
|
||||
|
||||
ParameterAccessor accessor =
|
||||
new ParametersParameterAccessor(parameters, values);
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
return new PageImpl<Object>(query.getResultList(),
|
||||
accessor.getPageable(), total);
|
||||
}
|
||||
}
|
||||
return query.createQuery(values).getSingleResult();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a {@link AbstractStringBasedJpaQuery} to return a single entity.
|
||||
*/
|
||||
static class SingleEntityExecution extends JpaQueryExecution {
|
||||
/**
|
||||
* Executes a modifying query such as an update, insert or delete.
|
||||
*/
|
||||
static class ModifyingExecution extends JpaQueryExecution {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
private final EntityManager em;
|
||||
|
||||
return query.createQuery(values).getSingleResult();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates an execution that automatically clears the given {@link EntityManager} after execution if the given
|
||||
* {@link EntityManager} is not {@literal null}.
|
||||
*
|
||||
* @param em
|
||||
*/
|
||||
public ModifyingExecution(JpaQueryMethod method, EntityManager em) {
|
||||
|
||||
/**
|
||||
* Executes a modifying query such as an update, insert or delete.
|
||||
*/
|
||||
static class ModifyingExecution extends JpaQueryExecution {
|
||||
Class<?> returnType = method.getReturnType();
|
||||
|
||||
private final EntityManager em;
|
||||
boolean isVoid = void.class.equals(returnType) || Void.class.equals(returnType);
|
||||
boolean isInt = int.class.equals(returnType) || Integer.class.equals(returnType);
|
||||
|
||||
Assert.isTrue(isInt || isVoid, "Modifying queries can only use void or int/Integer as return type!");
|
||||
|
||||
/**
|
||||
* Creates an execution that automatically clears the given
|
||||
* {@link EntityManager} after execution if the given
|
||||
* {@link EntityManager} is not {@literal null}.
|
||||
*
|
||||
* @param em
|
||||
*/
|
||||
public ModifyingExecution(JpaQueryMethod method, EntityManager em) {
|
||||
this.em = em;
|
||||
}
|
||||
|
||||
Class<?> returnType = method.getReturnType();
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
boolean isVoid =
|
||||
void.class.equals(returnType)
|
||||
|| Void.class.equals(returnType);
|
||||
boolean isInt =
|
||||
int.class.equals(returnType)
|
||||
|| Integer.class.equals(returnType);
|
||||
int result = query.createQuery(values).executeUpdate();
|
||||
|
||||
Assert.isTrue(isInt || isVoid,
|
||||
"Modifying queries can only use void or int/Integer as return type!");
|
||||
if (em != null) {
|
||||
em.clear();
|
||||
}
|
||||
|
||||
this.em = em;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
int result = query.createQuery(values).executeUpdate();
|
||||
|
||||
if (em != null) {
|
||||
em.clear();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
|
||||
/**
|
||||
* Query lookup strategy to execute finders.
|
||||
*
|
||||
@@ -36,186 +35,154 @@ import org.springframework.data.repository.query.RepositoryQuery;
|
||||
*/
|
||||
public final class JpaQueryLookupStrategy {
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private JpaQueryLookupStrategy() {
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private JpaQueryLookupStrategy() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for {@link QueryLookupStrategy} implementations that need
|
||||
* access to an {@link EntityManager}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private abstract static class AbstractQueryLookupStrategy implements
|
||||
QueryLookupStrategy {
|
||||
/**
|
||||
* Base class for {@link QueryLookupStrategy} implementations that need access to an {@link EntityManager}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private abstract static class AbstractQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
private final EntityManager em;
|
||||
private final QueryExtractor provider;
|
||||
private final EntityManager em;
|
||||
private final QueryExtractor provider;
|
||||
|
||||
public AbstractQueryLookupStrategy(EntityManager em, QueryExtractor extractor) {
|
||||
|
||||
public AbstractQueryLookupStrategy(EntityManager em,
|
||||
QueryExtractor extractor) {
|
||||
this.em = em;
|
||||
this.provider = extractor;
|
||||
}
|
||||
|
||||
this.em = em;
|
||||
this.provider = extractor;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#
|
||||
* resolveQuery(java.lang.reflect.Method,
|
||||
* org.springframework.data.repository.core.RepositoryMetadata,
|
||||
* org.springframework.data.repository.core.NamedQueries)
|
||||
*/
|
||||
public final RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
|
||||
|
||||
return resolveQuery(new JpaQueryMethod(method, metadata, provider), em, namedQueries);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#
|
||||
* resolveQuery(java.lang.reflect.Method,
|
||||
* org.springframework.data.repository.core.RepositoryMetadata,
|
||||
* org.springframework.data.repository.core.NamedQueries)
|
||||
*/
|
||||
public final RepositoryQuery resolveQuery(Method method,
|
||||
RepositoryMetadata metadata, NamedQueries namedQueries) {
|
||||
protected abstract RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries);
|
||||
}
|
||||
|
||||
return resolveQuery(new JpaQueryMethod(method, metadata, provider),
|
||||
em, namedQueries);
|
||||
}
|
||||
/**
|
||||
* {@link QueryLookupStrategy} to create a query from the method name.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class CreateQueryLookupStrategy extends AbstractQueryLookupStrategy {
|
||||
|
||||
public CreateQueryLookupStrategy(EntityManager em, QueryExtractor extractor) {
|
||||
|
||||
protected abstract RepositoryQuery resolveQuery(JpaQueryMethod method,
|
||||
EntityManager em, NamedQueries namedQueries);
|
||||
}
|
||||
super(em, extractor);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link QueryLookupStrategy} to create a query from the method name.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class CreateQueryLookupStrategy extends
|
||||
AbstractQueryLookupStrategy {
|
||||
@Override
|
||||
protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
|
||||
|
||||
public CreateQueryLookupStrategy(EntityManager em,
|
||||
QueryExtractor extractor) {
|
||||
return new PartTreeJpaQuery(method, em);
|
||||
}
|
||||
}
|
||||
|
||||
super(em, extractor);
|
||||
}
|
||||
/**
|
||||
* {@link QueryLookupStrategy} that tries to detect a declared query declared via {@link Query} annotation followed by
|
||||
* a JPA named query lookup.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class DeclaredQueryLookupStrategy extends AbstractQueryLookupStrategy {
|
||||
|
||||
public DeclaredQueryLookupStrategy(EntityManager em, QueryExtractor extractor) {
|
||||
|
||||
@Override
|
||||
protected RepositoryQuery resolveQuery(JpaQueryMethod method,
|
||||
EntityManager em, NamedQueries namedQueries) {
|
||||
super(em, extractor);
|
||||
}
|
||||
|
||||
return new PartTreeJpaQuery(method, em);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
|
||||
|
||||
/**
|
||||
* {@link QueryLookupStrategy} that tries to detect a declared query
|
||||
* declared via {@link Query} annotation followed by a JPA named query
|
||||
* lookup.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class DeclaredQueryLookupStrategy extends
|
||||
AbstractQueryLookupStrategy {
|
||||
RepositoryQuery query = SimpleJpaQuery.fromQueryAnnotation(method, em);
|
||||
|
||||
public DeclaredQueryLookupStrategy(EntityManager em,
|
||||
QueryExtractor extractor) {
|
||||
if (null != query) {
|
||||
return query;
|
||||
}
|
||||
|
||||
super(em, extractor);
|
||||
}
|
||||
String name = method.getNamedQueryName();
|
||||
if (namedQueries.hasQuery(name)) {
|
||||
return new SimpleJpaQuery(method, em, namedQueries.getQuery(name));
|
||||
}
|
||||
|
||||
query = NamedQuery.lookupFrom(method, em);
|
||||
|
||||
@Override
|
||||
protected RepositoryQuery resolveQuery(JpaQueryMethod method,
|
||||
EntityManager em, NamedQueries namedQueries) {
|
||||
if (null != query) {
|
||||
return query;
|
||||
}
|
||||
|
||||
RepositoryQuery query =
|
||||
SimpleJpaQuery.fromQueryAnnotation(method, em);
|
||||
throw new IllegalStateException(String.format(
|
||||
"Did neither find a NamedQuery nor an annotated query for method %s!", method));
|
||||
}
|
||||
|
||||
if (null != query) {
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
String name = method.getNamedQueryName();
|
||||
if (namedQueries.hasQuery(name)) {
|
||||
return new SimpleJpaQuery(method, em,
|
||||
namedQueries.getQuery(name));
|
||||
}
|
||||
/**
|
||||
* {@link QueryLookupStrategy} to try to detect a declared query first ( {@link Query}, JPA named query). In case none
|
||||
* is found we fall back on query creation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class CreateIfNotFoundQueryLookupStrategy extends AbstractQueryLookupStrategy {
|
||||
|
||||
query = NamedQuery.lookupFrom(method, em);
|
||||
private final DeclaredQueryLookupStrategy strategy;
|
||||
private final CreateQueryLookupStrategy createStrategy;
|
||||
|
||||
if (null != query) {
|
||||
return query;
|
||||
}
|
||||
public CreateIfNotFoundQueryLookupStrategy(EntityManager em, QueryExtractor extractor) {
|
||||
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
"Did neither find a NamedQuery nor an annotated query for method %s!",
|
||||
method));
|
||||
}
|
||||
super(em, extractor);
|
||||
this.strategy = new DeclaredQueryLookupStrategy(em, extractor);
|
||||
this.createStrategy = new CreateQueryLookupStrategy(em, extractor);
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
|
||||
|
||||
/**
|
||||
* {@link QueryLookupStrategy} to try to detect a declared query first (
|
||||
* {@link Query}, JPA named query). In case none is found we fall back on
|
||||
* query creation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class CreateIfNotFoundQueryLookupStrategy extends
|
||||
AbstractQueryLookupStrategy {
|
||||
try {
|
||||
return strategy.resolveQuery(method, em, namedQueries);
|
||||
} catch (IllegalStateException e) {
|
||||
return createStrategy.resolveQuery(method, em, namedQueries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final DeclaredQueryLookupStrategy strategy;
|
||||
private final CreateQueryLookupStrategy createStrategy;
|
||||
/**
|
||||
* Creates a {@link QueryLookupStrategy} for the given {@link EntityManager} and {@link Key}.
|
||||
*
|
||||
* @param em
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static QueryLookupStrategy create(EntityManager em, Key key, QueryExtractor extractor) {
|
||||
|
||||
if (key == null) {
|
||||
return new CreateIfNotFoundQueryLookupStrategy(em, extractor);
|
||||
}
|
||||
|
||||
public CreateIfNotFoundQueryLookupStrategy(EntityManager em,
|
||||
QueryExtractor extractor) {
|
||||
|
||||
super(em, extractor);
|
||||
this.strategy = new DeclaredQueryLookupStrategy(em, extractor);
|
||||
this.createStrategy = new CreateQueryLookupStrategy(em, extractor);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected RepositoryQuery resolveQuery(JpaQueryMethod method,
|
||||
EntityManager em, NamedQueries namedQueries) {
|
||||
|
||||
try {
|
||||
return strategy.resolveQuery(method, em, namedQueries);
|
||||
} catch (IllegalStateException e) {
|
||||
return createStrategy.resolveQuery(method, em, namedQueries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link QueryLookupStrategy} for the given {@link EntityManager}
|
||||
* and {@link Key}.
|
||||
*
|
||||
* @param em
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static QueryLookupStrategy create(EntityManager em, Key key,
|
||||
QueryExtractor extractor) {
|
||||
|
||||
if (key == null) {
|
||||
return new CreateIfNotFoundQueryLookupStrategy(em, extractor);
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case CREATE:
|
||||
return new CreateQueryLookupStrategy(em, extractor);
|
||||
case USE_DECLARED_QUERY:
|
||||
return new DeclaredQueryLookupStrategy(em, extractor);
|
||||
case CREATE_IF_NOT_FOUND:
|
||||
return new CreateIfNotFoundQueryLookupStrategy(em, extractor);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Unsupported query lookup strategy %s!", key));
|
||||
}
|
||||
}
|
||||
switch (key) {
|
||||
case CREATE:
|
||||
return new CreateQueryLookupStrategy(em, extractor);
|
||||
case USE_DECLARED_QUERY:
|
||||
return new DeclaredQueryLookupStrategy(em, extractor);
|
||||
case CREATE_IF_NOT_FOUND:
|
||||
return new CreateIfNotFoundQueryLookupStrategy(em, extractor);
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s!", key));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* JPA specific extension of {@link QueryMethod}.
|
||||
*
|
||||
@@ -42,137 +41,119 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class JpaQueryMethod extends QueryMethod {
|
||||
|
||||
private final QueryExtractor extractor;
|
||||
private final Method method;
|
||||
private final QueryExtractor extractor;
|
||||
private final Method method;
|
||||
|
||||
/**
|
||||
* Creates a {@link JpaQueryMethod}.
|
||||
*
|
||||
* @param method must not be {@literal null}
|
||||
* @param extractor must not be {@literal null}
|
||||
* @param metadata must not be {@literal null}
|
||||
*/
|
||||
public JpaQueryMethod(Method method, RepositoryMetadata metadata, QueryExtractor extractor) {
|
||||
|
||||
/**
|
||||
* Creates a {@link JpaQueryMethod}.
|
||||
*
|
||||
* @param method must not be {@literal null}
|
||||
* @param extractor must not be {@literal null}
|
||||
* @param metadata must not be {@literal null}
|
||||
*/
|
||||
public JpaQueryMethod(Method method, RepositoryMetadata metadata,
|
||||
QueryExtractor extractor) {
|
||||
super(method, metadata);
|
||||
|
||||
super(method, metadata);
|
||||
Assert.notNull(method, "Method must not be null!");
|
||||
Assert.notNull(extractor, "Query extractor must not be null!");
|
||||
|
||||
Assert.notNull(method, "Method must not be null!");
|
||||
Assert.notNull(extractor, "Query extractor must not be null!");
|
||||
this.method = method;
|
||||
this.extractor = extractor;
|
||||
|
||||
this.method = method;
|
||||
this.extractor = extractor;
|
||||
Assert.isTrue(!(isModifyingQuery() && getParameters().hasSpecialParameter()),
|
||||
String.format("Modifying method must not contain %s!", Parameters.TYPES));
|
||||
}
|
||||
|
||||
Assert.isTrue(!(isModifyingQuery() && getParameters()
|
||||
.hasSpecialParameter()), String.format(
|
||||
"Modifying method must not contain %s!", Parameters.TYPES));
|
||||
}
|
||||
/**
|
||||
* Returns whether the finder is a modifying one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected boolean isModifyingQuery() {
|
||||
|
||||
return null != method.getAnnotation(Modifying.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the finder is a modifying one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected boolean isModifyingQuery() {
|
||||
/**
|
||||
* Returns all {@link QueryHint}s annotated at this class. Note, that {@link QueryHints}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<QueryHint> getHints() {
|
||||
|
||||
return null != method.getAnnotation(Modifying.class);
|
||||
}
|
||||
List<QueryHint> result = new ArrayList<QueryHint>();
|
||||
|
||||
QueryHints hints = getAnnotation(method, QueryHints.class);
|
||||
if (hints != null) {
|
||||
result.addAll(Arrays.asList(hints.value()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link QueryHint}s annotated at this class. Note, that
|
||||
* {@link QueryHints}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<QueryHint> getHints() {
|
||||
return result;
|
||||
}
|
||||
|
||||
List<QueryHint> result = new ArrayList<QueryHint>();
|
||||
/**
|
||||
* Returns the {@link QueryExtractor}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
QueryExtractor getQueryExtractor() {
|
||||
|
||||
QueryHints hints = getAnnotation(method, QueryHints.class);
|
||||
if (hints != null) {
|
||||
result.addAll(Arrays.asList(hints.value()));
|
||||
}
|
||||
return extractor;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Returns the actual return type of the method.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?> getReturnType() {
|
||||
|
||||
return method.getReturnType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link QueryExtractor}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
QueryExtractor getQueryExtractor() {
|
||||
/**
|
||||
* Returns the query string declared in a {@link Query} annotation or {@literal null} if neither the annotation found
|
||||
* nor the attribute was specified.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getAnnotatedQuery() {
|
||||
|
||||
return extractor;
|
||||
}
|
||||
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
|
||||
return StringUtils.hasText(query) ? query : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the countQuery string declared in a {@link Query} annotation or {@literal null} if neither the annotation
|
||||
* found nor the attribute was specified.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getCountQuery() {
|
||||
|
||||
/**
|
||||
* Returns the actual return type of the method.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?> getReturnType() {
|
||||
String countQuery = (String) AnnotationUtils.getValue(getQueryAnnotation(), "countQuery");
|
||||
return StringUtils.hasText(countQuery) ? countQuery : null;
|
||||
}
|
||||
|
||||
return method.getReturnType();
|
||||
}
|
||||
/**
|
||||
* Returns whether we should clear automatically for modifying queries.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean getClearAutomatically() {
|
||||
|
||||
return (Boolean) AnnotationUtils.getValue(method.getAnnotation(Modifying.class), "clearAutomatically");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the query string declared in a {@link Query} annotation or
|
||||
* {@literal null} if neither the annotation found nor the attribute was
|
||||
* specified.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getAnnotatedQuery() {
|
||||
/**
|
||||
* Returns the {@link Query} annotation that is applied to the method or {@code null} if none available.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Query getQueryAnnotation() {
|
||||
|
||||
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
|
||||
return StringUtils.hasText(query) ? query : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the countQuery string declared in a {@link Query} annotation or
|
||||
* {@literal null} if neither the annotation found nor the attribute was
|
||||
* specified.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getCountQuery() {
|
||||
|
||||
String countQuery =
|
||||
(String) AnnotationUtils.getValue(getQueryAnnotation(),
|
||||
"countQuery");
|
||||
return StringUtils.hasText(countQuery) ? countQuery : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether we should clear automatically for modifying queries.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean getClearAutomatically() {
|
||||
|
||||
return (Boolean) AnnotationUtils.getValue(
|
||||
method.getAnnotation(Modifying.class), "clearAutomatically");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@link Query} annotation that is applied to the method or
|
||||
* {@code null} if none available.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Query getQueryAnnotation() {
|
||||
|
||||
return method.getAnnotation(Query.class);
|
||||
}
|
||||
return method.getAnnotation(Query.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,125 +25,110 @@ import org.springframework.data.repository.query.QueryCreationException;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@link RepositoryQuery} based on
|
||||
* {@link javax.persistence.NamedQuery}s.
|
||||
* Implementation of {@link RepositoryQuery} based on {@link javax.persistence.NamedQuery}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
final class NamedQuery extends AbstractJpaQuery {
|
||||
|
||||
private static final String CANNOT_EXTRACT_QUERY =
|
||||
"Your persistence provider does not support extracting the JPQL query from a "
|
||||
+ "named query thus you can't use Pageable inside your query method. Make sure you "
|
||||
+ "have a JpaDialect configured at your EntityManagerFactoryBean as this affects "
|
||||
+ "discovering the concrete persistence provider.";
|
||||
private static final String CANNOT_EXTRACT_QUERY = "Your persistence provider does not support extracting the JPQL query from a "
|
||||
+ "named query thus you can't use Pageable inside your query method. Make sure you "
|
||||
+ "have a JpaDialect configured at your EntityManagerFactoryBean as this affects "
|
||||
+ "discovering the concrete persistence provider.";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NamedQuery.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NamedQuery.class);
|
||||
|
||||
private final String queryName;
|
||||
private final QueryExtractor extractor;
|
||||
private final String queryName;
|
||||
private final QueryExtractor extractor;
|
||||
|
||||
/**
|
||||
* Creates a new {@link NamedQuery}.
|
||||
*/
|
||||
private NamedQuery(JpaQueryMethod method, EntityManager em) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link NamedQuery}.
|
||||
*/
|
||||
private NamedQuery(JpaQueryMethod method, EntityManager em) {
|
||||
super(method, em);
|
||||
|
||||
super(method, em);
|
||||
this.queryName = method.getNamedQueryName();
|
||||
this.extractor = method.getQueryExtractor();
|
||||
|
||||
this.queryName = method.getNamedQueryName();
|
||||
this.extractor = method.getQueryExtractor();
|
||||
Parameters parameters = method.getParameters();
|
||||
|
||||
Parameters parameters = method.getParameters();
|
||||
if (parameters.hasSortParameter()) {
|
||||
throw new IllegalStateException(String.format("Finder method %s is backed " + "by a NamedQuery and must "
|
||||
+ "not contain a sort parameter as we " + "cannot modify the query! Use @Query instead!", method));
|
||||
}
|
||||
|
||||
if (parameters.hasSortParameter()) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Finder method %s is backed " + "by a NamedQuery and must "
|
||||
+ "not contain a sort parameter as we "
|
||||
+ "cannot modify the query! Use @Query instead!",
|
||||
method));
|
||||
}
|
||||
if (parameters.hasPageableParameter()) {
|
||||
LOG.info("Finder method {} is backed by a NamedQuery" + " but contains a Pageble parameter! Sorting deliviered "
|
||||
+ "via this Pageable will not be applied!", method);
|
||||
}
|
||||
|
||||
if (parameters.hasPageableParameter()) {
|
||||
LOG.info("Finder method {} is backed by a NamedQuery"
|
||||
+ " but contains a Pageble parameter! Sorting deliviered "
|
||||
+ "via this Pageable will not be applied!", method);
|
||||
}
|
||||
boolean weNeedToCreateCountQuery = method.getParameters().hasPageableParameter();
|
||||
boolean cantExtractQuery = !this.extractor.canExtractQuery();
|
||||
|
||||
boolean weNeedToCreateCountQuery =
|
||||
method.getParameters().hasPageableParameter();
|
||||
boolean cantExtractQuery = !this.extractor.canExtractQuery();
|
||||
if (weNeedToCreateCountQuery && cantExtractQuery) {
|
||||
throw QueryCreationException.create(method, CANNOT_EXTRACT_QUERY);
|
||||
}
|
||||
|
||||
if (weNeedToCreateCountQuery && cantExtractQuery) {
|
||||
throw QueryCreationException.create(method, CANNOT_EXTRACT_QUERY);
|
||||
}
|
||||
Query query = em.createNamedQuery(queryName);
|
||||
|
||||
Query query = em.createNamedQuery(queryName);
|
||||
// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=322579
|
||||
// until it gets fixed
|
||||
if (null != query) {
|
||||
query.getHints();
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=322579
|
||||
// until it gets fixed
|
||||
if (null != query) {
|
||||
query.getHints();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Looks up a named query for the given {@link QueryMethod}.
|
||||
*
|
||||
* @param method
|
||||
* @return
|
||||
*/
|
||||
public static RepositoryQuery lookupFrom(JpaQueryMethod method, EntityManager em) {
|
||||
|
||||
final String queryName = method.getNamedQueryName();
|
||||
|
||||
/**
|
||||
* Looks up a named query for the given {@link QueryMethod}.
|
||||
*
|
||||
* @param method
|
||||
* @return
|
||||
*/
|
||||
public static RepositoryQuery lookupFrom(JpaQueryMethod method,
|
||||
EntityManager em) {
|
||||
LOG.debug("Looking up named query {}", queryName);
|
||||
|
||||
final String queryName = method.getNamedQueryName();
|
||||
try {
|
||||
return new NamedQuery(method, em);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug("Looking up named query {}", queryName);
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.AbstractStringBasedJpaQuery
|
||||
* #
|
||||
* createQuery(org.springframework.data.jpa.repository.query.ParameterBinder
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
protected Query createQuery(Object[] values) {
|
||||
|
||||
try {
|
||||
return new NamedQuery(method, em);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Query query = getEntityManager().createNamedQuery(queryName);
|
||||
return createBinder(values).bindAndPrepare(query);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.AbstractStringBasedJpaQuery
|
||||
* #createCountQuery(org.springframework.data.jpa.repository.query.
|
||||
* ParameterBinder)
|
||||
*/
|
||||
@Override
|
||||
protected Query createCountQuery(Object[] values) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.AbstractStringBasedJpaQuery
|
||||
* #
|
||||
* createQuery(org.springframework.data.jpa.repository.query.ParameterBinder
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
protected Query createQuery(Object[] values) {
|
||||
Query query = createQuery(values);
|
||||
String queryString = extractor.extractQueryString(query);
|
||||
|
||||
Query query = getEntityManager().createNamedQuery(queryName);
|
||||
return createBinder(values).bindAndPrepare(query);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.AbstractStringBasedJpaQuery
|
||||
* #createCountQuery(org.springframework.data.jpa.repository.query.
|
||||
* ParameterBinder)
|
||||
*/
|
||||
@Override
|
||||
protected Query createCountQuery(Object[] values) {
|
||||
|
||||
Query query = createQuery(values);
|
||||
String queryString = extractor.extractQueryString(query);
|
||||
|
||||
return createBinder(values).bind(
|
||||
getEntityManager().createQuery(
|
||||
QueryUtils.createCountQueryFor(queryString)));
|
||||
}
|
||||
return createBinder(values).bind(getEntityManager().createQuery(QueryUtils.createCountQueryFor(queryString)));
|
||||
}
|
||||
}
|
||||
@@ -23,149 +23,133 @@ import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* {@link ParameterBinder} is used to bind method parameters to a {@link Query}.
|
||||
* This is usually done whenever an {@link AbstractJpaQuery} is executed.
|
||||
* {@link ParameterBinder} is used to bind method parameters to a {@link Query}. This is usually done whenever an
|
||||
* {@link AbstractJpaQuery} is executed.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ParameterBinder {
|
||||
|
||||
private final Parameters parameters;
|
||||
private final Object[] values;
|
||||
private final Parameters parameters;
|
||||
private final Object[] values;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ParameterBinder}.
|
||||
*
|
||||
* @param parameters
|
||||
* @param values
|
||||
*/
|
||||
public ParameterBinder(Parameters parameters, Object[] values) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ParameterBinder}.
|
||||
*
|
||||
* @param parameters
|
||||
* @param values
|
||||
*/
|
||||
public ParameterBinder(Parameters parameters, Object[] values) {
|
||||
Assert.notNull(parameters);
|
||||
Assert.notNull(values);
|
||||
|
||||
Assert.notNull(parameters);
|
||||
Assert.notNull(values);
|
||||
Assert.isTrue(parameters.getNumberOfParameters() == values.length, "Invalid number of parameters given!");
|
||||
|
||||
Assert.isTrue(parameters.getNumberOfParameters() == values.length,
|
||||
"Invalid number of parameters given!");
|
||||
this.parameters = parameters;
|
||||
this.values = values.clone();
|
||||
}
|
||||
|
||||
this.parameters = parameters;
|
||||
this.values = values.clone();
|
||||
}
|
||||
ParameterBinder(Parameters parameters) {
|
||||
|
||||
this(parameters, new Object[0]);
|
||||
}
|
||||
|
||||
ParameterBinder(Parameters parameters) {
|
||||
/**
|
||||
* Returns the {@link Pageable} of the parameters, if available. Returns {@code null} otherwise.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Pageable getPageable() {
|
||||
|
||||
this(parameters, new Object[0]);
|
||||
}
|
||||
if (!parameters.hasPageableParameter()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (Pageable) values[parameters.getPageableIndex()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Pageable} of the parameters, if available. Returns
|
||||
* {@code null} otherwise.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Pageable getPageable() {
|
||||
/**
|
||||
* Returns the sort instance to be used for query creation. Will use a {@link Sort} parameter if available or the
|
||||
* {@link Sort} contained in a {@link Pageable} if available. Returns {@code null} if no {@link Sort} can be found.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Sort getSort() {
|
||||
|
||||
if (!parameters.hasPageableParameter()) {
|
||||
return null;
|
||||
}
|
||||
if (parameters.hasSortParameter()) {
|
||||
return (Sort) values[parameters.getSortIndex()];
|
||||
}
|
||||
|
||||
return (Pageable) values[parameters.getPageableIndex()];
|
||||
}
|
||||
if (parameters.hasPageableParameter() && getPageable() != null) {
|
||||
return getPageable().getSort();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sort instance to be used for query creation. Will use a
|
||||
* {@link Sort} parameter if available or the {@link Sort} contained in a
|
||||
* {@link Pageable} if available. Returns {@code null} if no {@link Sort}
|
||||
* can be found.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Sort getSort() {
|
||||
/**
|
||||
* Binds the parameters to the given {@link Query}.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public Query bind(Query query) {
|
||||
|
||||
if (parameters.hasSortParameter()) {
|
||||
return (Sort) values[parameters.getSortIndex()];
|
||||
}
|
||||
int methodParameterPosition = 0;
|
||||
int queryParameterPosition = 1;
|
||||
|
||||
if (parameters.hasPageableParameter() && getPageable() != null) {
|
||||
return getPageable().getSort();
|
||||
}
|
||||
for (Parameter parameter : parameters) {
|
||||
|
||||
return null;
|
||||
}
|
||||
if (parameter.isBindable()) {
|
||||
|
||||
Object value = values[methodParameterPosition];
|
||||
bind(query, parameter, value, queryParameterPosition++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the parameters to the given {@link Query}.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public Query bind(Query query) {
|
||||
methodParameterPosition++;
|
||||
}
|
||||
|
||||
int methodParameterPosition = 0;
|
||||
int queryParameterPosition = 1;
|
||||
return query;
|
||||
}
|
||||
|
||||
for (Parameter parameter : parameters) {
|
||||
protected void bind(Query query, Parameter parameter, Object value, int position) {
|
||||
|
||||
if (parameter.isBindable()) {
|
||||
if (hasNamedParameter(query) && parameter.isNamedParameter()) {
|
||||
query.setParameter(parameter.getName(), value);
|
||||
} else {
|
||||
query.setParameter(position, value);
|
||||
}
|
||||
}
|
||||
|
||||
Object value = values[methodParameterPosition];
|
||||
bind(query, parameter, value, queryParameterPosition++);
|
||||
}
|
||||
/**
|
||||
* Binds the parameters to the given query and applies special parameter types (e.g. pagination).
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public Query bindAndPrepare(Query query) {
|
||||
|
||||
methodParameterPosition++;
|
||||
}
|
||||
return bindAndPrepare(query, parameters);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
private Query bindAndPrepare(Query query, Parameters parameters) {
|
||||
|
||||
Query result = bind(query);
|
||||
|
||||
protected void bind(Query query, Parameter parameter, Object value,
|
||||
int position) {
|
||||
if (!parameters.hasPageableParameter() || getPageable() == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (hasNamedParameter(query) && parameter.isNamedParameter()) {
|
||||
query.setParameter(parameter.getName(), value);
|
||||
} else {
|
||||
query.setParameter(position, value);
|
||||
}
|
||||
}
|
||||
result.setFirstResult(getPageable().getOffset());
|
||||
result.setMaxResults(getPageable().getPageSize());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the parameters to the given query and applies special parameter
|
||||
* types (e.g. pagination).
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public Query bindAndPrepare(Query query) {
|
||||
boolean hasNamedParameter(Query query) {
|
||||
|
||||
return bindAndPrepare(query, parameters);
|
||||
}
|
||||
|
||||
|
||||
private Query bindAndPrepare(Query query, Parameters parameters) {
|
||||
|
||||
Query result = bind(query);
|
||||
|
||||
if (!parameters.hasPageableParameter() || getPageable() == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.setFirstResult(getPageable().getOffset());
|
||||
result.setMaxResults(getPageable().getPageSize());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
boolean hasNamedParameter(Query query) {
|
||||
|
||||
return QueryUtils.hasNamedParameter(query);
|
||||
}
|
||||
return QueryUtils.hasNamedParameter(query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link AbstractJpaQuery} implementation based on a {@link PartTree}.
|
||||
*
|
||||
@@ -36,179 +35,157 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
*/
|
||||
public class PartTreeJpaQuery extends AbstractJpaQuery {
|
||||
|
||||
private final Class<?> domainClass;
|
||||
private final PartTree tree;
|
||||
private final Parameters parameters;
|
||||
private final Class<?> domainClass;
|
||||
private final PartTree tree;
|
||||
private final Parameters parameters;
|
||||
|
||||
private final QueryPreparer query;
|
||||
private final QueryPreparer countQuery;
|
||||
private final QueryPreparer query;
|
||||
private final QueryPreparer countQuery;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PartTreeJpaQuery}.
|
||||
*
|
||||
* @param method
|
||||
* @param em
|
||||
*/
|
||||
public PartTreeJpaQuery(JpaQueryMethod method, EntityManager em) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link PartTreeJpaQuery}.
|
||||
*
|
||||
* @param method
|
||||
* @param em
|
||||
*/
|
||||
public PartTreeJpaQuery(JpaQueryMethod method, EntityManager em) {
|
||||
super(method, em);
|
||||
|
||||
super(method, em);
|
||||
this.domainClass = method.getEntityInformation().getJavaType();
|
||||
this.tree = new PartTree(method.getName(), domainClass);
|
||||
this.parameters = method.getParameters();
|
||||
|
||||
this.domainClass = method.getEntityInformation().getJavaType();
|
||||
this.tree = new PartTree(method.getName(), domainClass);
|
||||
this.parameters = method.getParameters();
|
||||
this.query = new QueryPreparer(parameters.potentiallySortsDynamically());
|
||||
this.countQuery = new CountQueryPreparer(parameters.potentiallySortsDynamically());
|
||||
}
|
||||
|
||||
this.query =
|
||||
new QueryPreparer(parameters.potentiallySortsDynamically());
|
||||
this.countQuery =
|
||||
new CountQueryPreparer(parameters.potentiallySortsDynamically());
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.AbstractJpaQuery#createQuery
|
||||
* (javax.persistence.EntityManager,
|
||||
* org.springframework.data.jpa.repository.query.ParameterBinder)
|
||||
*/
|
||||
@Override
|
||||
public Query createQuery(Object[] values) {
|
||||
|
||||
return query.createQuery(values);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.AbstractJpaQuery#createQuery
|
||||
* (javax.persistence.EntityManager,
|
||||
* org.springframework.data.jpa.repository.query.ParameterBinder)
|
||||
*/
|
||||
@Override
|
||||
public Query createQuery(Object[] values) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.query.AbstractJpaQuery#
|
||||
* createCountQuery(javax.persistence.EntityManager)
|
||||
*/
|
||||
@Override
|
||||
public Query createCountQuery(Object[] values) {
|
||||
|
||||
return query.createQuery(values);
|
||||
}
|
||||
return countQuery.createQuery(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query preparer to create {@link CriteriaQuery} instances and potentially cache them.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class QueryPreparer {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.query.AbstractJpaQuery#
|
||||
* createCountQuery(javax.persistence.EntityManager)
|
||||
*/
|
||||
@Override
|
||||
public Query createCountQuery(Object[] values) {
|
||||
private final CriteriaQuery<?> query;
|
||||
private final List<ParameterExpression<?>> expressions;
|
||||
|
||||
return countQuery.createQuery(values);
|
||||
}
|
||||
public QueryPreparer(boolean recreateQueries) {
|
||||
|
||||
/**
|
||||
* Query preparer to create {@link CriteriaQuery} instances and potentially
|
||||
* cache them.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class QueryPreparer {
|
||||
JpaQueryCreator creator = createCreator();
|
||||
this.query = recreateQueries ? null : creator.createQuery();
|
||||
this.expressions = recreateQueries ? null : creator.getParameterExpressions();
|
||||
}
|
||||
|
||||
private final CriteriaQuery<?> query;
|
||||
private final List<ParameterExpression<?>> expressions;
|
||||
/**
|
||||
* Creates a new {@link Query} for the given parameter values.
|
||||
*
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
public Query createQuery(Object[] values) {
|
||||
|
||||
CriteriaQuery<?> criteriaQuery = query;
|
||||
List<ParameterExpression<?>> expressions = this.expressions;
|
||||
|
||||
public QueryPreparer(boolean recreateQueries) {
|
||||
if (query == null) {
|
||||
JpaQueryCreator creator = createCreator();
|
||||
criteriaQuery = creator.createQuery(getDynamicSort(values));
|
||||
expressions = creator.getParameterExpressions();
|
||||
}
|
||||
|
||||
JpaQueryCreator creator = createCreator();
|
||||
this.query = recreateQueries ? null : creator.createQuery();
|
||||
this.expressions =
|
||||
recreateQueries ? null : creator.getParameterExpressions();
|
||||
}
|
||||
TypedQuery<?> jpaQuery = getEntityManager().createQuery(criteriaQuery);
|
||||
return invokeBinding(getBinder(values, expressions), jpaQuery);
|
||||
}
|
||||
|
||||
protected JpaQueryCreator createCreator() {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Query} for the given parameter values.
|
||||
*
|
||||
* @param values
|
||||
* @return
|
||||
*/
|
||||
public Query createQuery(Object[] values) {
|
||||
return new JpaQueryCreator(tree, domainClass, parameters, getEntityManager());
|
||||
}
|
||||
|
||||
CriteriaQuery<?> criteriaQuery = query;
|
||||
List<ParameterExpression<?>> expressions = this.expressions;
|
||||
/**
|
||||
* Invokes parameter binding on the given {@link TypedQuery}.
|
||||
*
|
||||
* @param binder
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
protected Query invokeBinding(ParameterBinder binder, TypedQuery<?> query) {
|
||||
|
||||
if (query == null) {
|
||||
JpaQueryCreator creator = createCreator();
|
||||
criteriaQuery = creator.createQuery(getDynamicSort(values));
|
||||
expressions = creator.getParameterExpressions();
|
||||
}
|
||||
return binder.bindAndPrepare(query);
|
||||
}
|
||||
|
||||
TypedQuery<?> jpaQuery =
|
||||
getEntityManager().createQuery(criteriaQuery);
|
||||
return invokeBinding(getBinder(values, expressions), jpaQuery);
|
||||
}
|
||||
private ParameterBinder getBinder(Object[] values, List<ParameterExpression<?>> expressions) {
|
||||
|
||||
return new CriteriaQueryParameterBinder(parameters, values, expressions);
|
||||
}
|
||||
|
||||
protected JpaQueryCreator createCreator() {
|
||||
private Sort getDynamicSort(Object[] values) {
|
||||
|
||||
return new JpaQueryCreator(tree, domainClass, parameters,
|
||||
getEntityManager());
|
||||
}
|
||||
return parameters.potentiallySortsDynamically() ? new ParametersParameterAccessor(parameters, values).getSort()
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special {@link QueryPreparer} to create count queries.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class CountQueryPreparer extends QueryPreparer {
|
||||
|
||||
/**
|
||||
* Invokes parameter binding on the given {@link TypedQuery}.
|
||||
*
|
||||
* @param binder
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
protected Query invokeBinding(ParameterBinder binder,
|
||||
TypedQuery<?> query) {
|
||||
public CountQueryPreparer(boolean recreateQueries) {
|
||||
|
||||
return binder.bindAndPrepare(query);
|
||||
}
|
||||
super(recreateQueries);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.query.PartTreeJpaQuery.
|
||||
* QueryPreparer#createCreator()
|
||||
*/
|
||||
@Override
|
||||
protected JpaQueryCreator createCreator() {
|
||||
|
||||
private ParameterBinder getBinder(Object[] values,
|
||||
List<ParameterExpression<?>> expressions) {
|
||||
return new JpaCountQueryCreator(tree, domainClass, parameters, getEntityManager());
|
||||
}
|
||||
|
||||
return new CriteriaQueryParameterBinder(parameters, values,
|
||||
expressions);
|
||||
}
|
||||
/**
|
||||
* Customizes binding by skipping the pagination.
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.query.PartTreeJpaQuery.QueryPreparer#invokeBinding(org.springframework.data.jpa.repository.query.ParameterBinder,
|
||||
* javax.persistence.TypedQuery)
|
||||
*/
|
||||
protected Query invokeBinding(ParameterBinder binder, javax.persistence.TypedQuery<?> query) {
|
||||
|
||||
|
||||
private Sort getDynamicSort(Object[] values) {
|
||||
|
||||
return parameters.potentiallySortsDynamically() ? new ParametersParameterAccessor(
|
||||
parameters, values).getSort() : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special {@link QueryPreparer} to create count queries.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class CountQueryPreparer extends QueryPreparer {
|
||||
|
||||
public CountQueryPreparer(boolean recreateQueries) {
|
||||
|
||||
super(recreateQueries);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.query.PartTreeJpaQuery.
|
||||
* QueryPreparer#createCreator()
|
||||
*/
|
||||
@Override
|
||||
protected JpaQueryCreator createCreator() {
|
||||
|
||||
return new JpaCountQueryCreator(tree, domainClass, parameters,
|
||||
getEntityManager());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Customizes binding by skipping the pagination.
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.query.PartTreeJpaQuery.QueryPreparer#invokeBinding(org.springframework.data.jpa.repository.query.ParameterBinder,
|
||||
* javax.persistence.TypedQuery)
|
||||
*/
|
||||
protected Query invokeBinding(ParameterBinder binder,
|
||||
javax.persistence.TypedQuery<?> query) {
|
||||
|
||||
return binder.bind(query);
|
||||
}
|
||||
}
|
||||
return binder.bind(query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,33 +17,26 @@ package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import javax.persistence.Query;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to hide different implementations to extract the original JPA query
|
||||
* string from a {@link Query}.
|
||||
* Interface to hide different implementations to extract the original JPA query string from a {@link Query}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface QueryExtractor {
|
||||
|
||||
/**
|
||||
* Reverse engineers the query string from the {@link Query} object. This
|
||||
* requires provider specific API as JPA does not provide access to the
|
||||
* underlying query string as soon as one has created a {@link Query}
|
||||
* instance of it.
|
||||
*
|
||||
* @param query
|
||||
* @return the query string representing the query or {@literal null} if
|
||||
* resolving is not possible.
|
||||
*/
|
||||
String extractQueryString(Query query);
|
||||
/**
|
||||
* Reverse engineers the query string from the {@link Query} object. This requires provider specific API as JPA does
|
||||
* not provide access to the underlying query string as soon as one has created a {@link Query} instance of it.
|
||||
*
|
||||
* @param query
|
||||
* @return the query string representing the query or {@literal null} if resolving is not possible.
|
||||
*/
|
||||
String extractQueryString(Query query);
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the extractor is able to extract the original query
|
||||
* string from a given {@link Query}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean canExtractQuery();
|
||||
/**
|
||||
* Returns whether the extractor is able to extract the original query string from a given {@link Query}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean canExtractQuery();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Simple utility class to create JPA queries.
|
||||
*
|
||||
@@ -44,273 +43,251 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public abstract class QueryUtils {
|
||||
|
||||
public static final String COUNT_QUERY_STRING =
|
||||
"select count(%s) from %s x";
|
||||
public static final String COUNT_QUERY_STRING = "select count(%s) from %s x";
|
||||
|
||||
public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";
|
||||
public static final String READ_ALL_QUERY = "select x from %s x";
|
||||
private static final String DEFAULT_ALIAS = "x";
|
||||
private static final String COUNT_REPLACEMENT = "select count($3$5) $4$5$6";
|
||||
public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";
|
||||
public static final String READ_ALL_QUERY = "select x from %s x";
|
||||
private static final String DEFAULT_ALIAS = "x";
|
||||
private static final String COUNT_REPLACEMENT = "select count($3$5) $4$5$6";
|
||||
|
||||
private static final Pattern ALIAS_MATCH;
|
||||
private static final Pattern COUNT_MATCH;
|
||||
|
||||
private static final String IDENTIFIER = "[\\p{L}._$]+";
|
||||
private static final String IDENTIFIER_GROUP = String.format("(%s)", IDENTIFIER);
|
||||
|
||||
static {
|
||||
|
||||
private static final Pattern ALIAS_MATCH;
|
||||
private static final Pattern COUNT_MATCH;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("(?<=from)"); // from as starting delimiter
|
||||
builder.append("(?: )+"); // at least one space separating
|
||||
builder.append(IDENTIFIER_GROUP); // Entity name, can be qualified (any
|
||||
builder.append("(?: as)*"); // exclude possible "as" keyword
|
||||
builder.append("(?: )+"); // at least one space separating
|
||||
builder.append("(\\w*)"); // the actual alias
|
||||
|
||||
ALIAS_MATCH = compile(builder.toString(), CASE_INSENSITIVE);
|
||||
|
||||
builder = new StringBuilder();
|
||||
builder.append("(select\\s+((distinct )?.+?)\\s+)?(from\\s+");
|
||||
builder.append(IDENTIFIER);
|
||||
builder.append("(?:\\s+as)?\\s+)");
|
||||
builder.append(IDENTIFIER_GROUP);
|
||||
builder.append("(.*)");
|
||||
|
||||
COUNT_MATCH = compile(builder.toString(), CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private QueryUtils() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the query string for the given class name.
|
||||
*
|
||||
* @param template
|
||||
* @param entityName
|
||||
* @return
|
||||
*/
|
||||
public static String getQueryString(String template, String entityName) {
|
||||
|
||||
private static final String IDENTIFIER = "[\\p{L}._$]+";
|
||||
private static final String IDENTIFIER_GROUP = String.format("(%s)",
|
||||
IDENTIFIER);
|
||||
Assert.hasText(entityName, "Entity name must not be null or empty!");
|
||||
|
||||
return String.format(template, entityName);
|
||||
}
|
||||
|
||||
static {
|
||||
/**
|
||||
* Adds {@literal order by} clause to the JPQL query. Uses the {@link #DEFAULT_ALIAS} to bind the sorting property to.
|
||||
*
|
||||
* @param query
|
||||
* @param alias
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
public static String applySorting(String query, Sort sort) {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("(?<=from)"); // from as starting delimiter
|
||||
builder.append("(?: )+"); // at least one space separating
|
||||
builder.append(IDENTIFIER_GROUP); // Entity name, can be qualified (any
|
||||
builder.append("(?: as)*"); // exclude possible "as" keyword
|
||||
builder.append("(?: )+"); // at least one space separating
|
||||
builder.append("(\\w*)"); // the actual alias
|
||||
return applySorting(query, sort, DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
ALIAS_MATCH = compile(builder.toString(), CASE_INSENSITIVE);
|
||||
/**
|
||||
* Adds {@literal order by} clause to the JPQL query.
|
||||
*
|
||||
* @param query
|
||||
* @param sort
|
||||
* @param alias
|
||||
* @return
|
||||
*/
|
||||
public static String applySorting(String query, Sort sort, String alias) {
|
||||
|
||||
builder = new StringBuilder();
|
||||
builder.append("(select\\s+((distinct )?.+?)\\s+)?(from\\s+");
|
||||
builder.append(IDENTIFIER);
|
||||
builder.append("(?:\\s+as)?\\s+)");
|
||||
builder.append(IDENTIFIER_GROUP);
|
||||
builder.append("(.*)");
|
||||
Assert.hasText(query);
|
||||
|
||||
COUNT_MATCH = compile(builder.toString(), CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private QueryUtils() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the query string for the given class name.
|
||||
*
|
||||
* @param template
|
||||
* @param entityName
|
||||
* @return
|
||||
*/
|
||||
public static String getQueryString(String template, String entityName) {
|
||||
|
||||
Assert.hasText(entityName, "Entity name must not be null or empty!");
|
||||
|
||||
return String.format(template, entityName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds {@literal order by} clause to the JPQL query. Uses the
|
||||
* {@link #DEFAULT_ALIAS} to bind the sorting property to.
|
||||
*
|
||||
* @param query
|
||||
* @param alias
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
public static String applySorting(String query, Sort sort) {
|
||||
|
||||
return applySorting(query, sort, DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds {@literal order by} clause to the JPQL query.
|
||||
*
|
||||
* @param query
|
||||
* @param sort
|
||||
* @param alias
|
||||
* @return
|
||||
*/
|
||||
public static String applySorting(String query, Sort sort, String alias) {
|
||||
|
||||
Assert.hasText(query);
|
||||
|
||||
if (null == sort) {
|
||||
return query;
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder(query);
|
||||
builder.append(" order by");
|
||||
|
||||
for (Order order : sort) {
|
||||
builder.append(String.format(" %s.%s %s,", alias,
|
||||
order.getProperty(), toJpaDirection(order)));
|
||||
}
|
||||
|
||||
builder.deleteCharAt(builder.length() - 1);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
public static String toJpaDirection(Order order) {
|
||||
|
||||
return order.getDirection().name().toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolves the alias for the entity to be retrieved from the given JPA
|
||||
* query.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public static String detectAlias(String query) {
|
||||
|
||||
Matcher matcher = ALIAS_MATCH.matcher(query);
|
||||
|
||||
return matcher.find() ? matcher.group(2) : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a where-clause referencing the given entities and appends it to
|
||||
* the given query string. Binds the given entities to the query.
|
||||
*
|
||||
* @param <T>
|
||||
* @param queryString
|
||||
* @param entities
|
||||
* @param entityManager
|
||||
* @return
|
||||
*/
|
||||
public static <T> Query applyAndBind(String queryString,
|
||||
Iterable<T> entities, EntityManager entityManager) {
|
||||
|
||||
Assert.notNull(queryString);
|
||||
Assert.notNull(entities);
|
||||
Assert.notNull(entityManager);
|
||||
|
||||
Iterator<T> iterator = entities.iterator();
|
||||
|
||||
if (!iterator.hasNext()) {
|
||||
return entityManager.createQuery(queryString);
|
||||
}
|
||||
|
||||
String alias = detectAlias(queryString);
|
||||
StringBuilder builder = new StringBuilder(queryString);
|
||||
builder.append(" where");
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
|
||||
iterator.next();
|
||||
|
||||
builder.append(String.format(" %s = ?%d", alias, ++i));
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
builder.append(" or");
|
||||
}
|
||||
}
|
||||
|
||||
Query query = entityManager.createQuery(builder.toString());
|
||||
|
||||
iterator = entities.iterator();
|
||||
i = 0;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
query.setParameter(++i, iterator.next());
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a count projected query from the given orginal query.
|
||||
*
|
||||
* @param originalQuery must not be {@literal null} or empty
|
||||
* @return
|
||||
*/
|
||||
public static String createCountQueryFor(String originalQuery) {
|
||||
|
||||
Assert.hasText(originalQuery);
|
||||
|
||||
Matcher matcher = COUNT_MATCH.matcher(originalQuery);
|
||||
return matcher.replaceFirst(COUNT_REPLACEMENT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link Query} contains named parameters.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public static boolean hasNamedParameter(Query query) {
|
||||
|
||||
for (Parameter<?> parameter : query.getParameters()) {
|
||||
if (parameter.getName() != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turns the given {@link Sort} into
|
||||
* {@link javax.persistence.criteria.Order}s.
|
||||
*
|
||||
* @param sort
|
||||
* @param root
|
||||
* @param cb
|
||||
* @return
|
||||
*/
|
||||
public static List<javax.persistence.criteria.Order> toOrders(Sort sort,
|
||||
Root<?> root, CriteriaBuilder cb) {
|
||||
|
||||
List<javax.persistence.criteria.Order> orders =
|
||||
new ArrayList<javax.persistence.criteria.Order>();
|
||||
|
||||
if (sort == null) {
|
||||
return orders;
|
||||
}
|
||||
|
||||
for (org.springframework.data.domain.Sort.Order order : sort) {
|
||||
orders.add(toJpaOrder(order, root, cb));
|
||||
}
|
||||
|
||||
return orders;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a criteria API {@link javax.persistence.criteria.Order} from the
|
||||
* given {@link Order}.
|
||||
*
|
||||
* @param order
|
||||
* @param root
|
||||
* @param cb
|
||||
* @return
|
||||
*/
|
||||
private static javax.persistence.criteria.Order toJpaOrder(Order order,
|
||||
Root<?> root, CriteriaBuilder cb) {
|
||||
|
||||
Expression<?> expression = null;
|
||||
String pathString = order.getProperty();
|
||||
String[] pathElements = pathString.split("\\.");
|
||||
int pathSize = pathElements.length;
|
||||
|
||||
if (pathSize > 1) {
|
||||
Join<Object, Object> path = root.join(pathElements[0]);
|
||||
for (int i = 1; i < pathSize - 1; i++) {
|
||||
path = path.join(pathElements[i]);
|
||||
}
|
||||
expression = path.get(pathElements[pathSize - 1]);
|
||||
} else {
|
||||
expression = root.get(pathString);
|
||||
}
|
||||
|
||||
return order.isAscending() ? cb.asc(expression) : cb.desc(expression);
|
||||
}
|
||||
if (null == sort) {
|
||||
return query;
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder(query);
|
||||
builder.append(" order by");
|
||||
|
||||
for (Order order : sort) {
|
||||
builder.append(String.format(" %s.%s %s,", alias, order.getProperty(), toJpaDirection(order)));
|
||||
}
|
||||
|
||||
builder.deleteCharAt(builder.length() - 1);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static String toJpaDirection(Order order) {
|
||||
|
||||
return order.getDirection().name().toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the alias for the entity to be retrieved from the given JPA query.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public static String detectAlias(String query) {
|
||||
|
||||
Matcher matcher = ALIAS_MATCH.matcher(query);
|
||||
|
||||
return matcher.find() ? matcher.group(2) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a where-clause referencing the given entities and appends it to the given query string. Binds the given
|
||||
* entities to the query.
|
||||
*
|
||||
* @param <T>
|
||||
* @param queryString
|
||||
* @param entities
|
||||
* @param entityManager
|
||||
* @return
|
||||
*/
|
||||
public static <T> Query applyAndBind(String queryString, Iterable<T> entities, EntityManager entityManager) {
|
||||
|
||||
Assert.notNull(queryString);
|
||||
Assert.notNull(entities);
|
||||
Assert.notNull(entityManager);
|
||||
|
||||
Iterator<T> iterator = entities.iterator();
|
||||
|
||||
if (!iterator.hasNext()) {
|
||||
return entityManager.createQuery(queryString);
|
||||
}
|
||||
|
||||
String alias = detectAlias(queryString);
|
||||
StringBuilder builder = new StringBuilder(queryString);
|
||||
builder.append(" where");
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
|
||||
iterator.next();
|
||||
|
||||
builder.append(String.format(" %s = ?%d", alias, ++i));
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
builder.append(" or");
|
||||
}
|
||||
}
|
||||
|
||||
Query query = entityManager.createQuery(builder.toString());
|
||||
|
||||
iterator = entities.iterator();
|
||||
i = 0;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
query.setParameter(++i, iterator.next());
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a count projected query from the given orginal query.
|
||||
*
|
||||
* @param originalQuery must not be {@literal null} or empty
|
||||
* @return
|
||||
*/
|
||||
public static String createCountQueryFor(String originalQuery) {
|
||||
|
||||
Assert.hasText(originalQuery);
|
||||
|
||||
Matcher matcher = COUNT_MATCH.matcher(originalQuery);
|
||||
return matcher.replaceFirst(COUNT_REPLACEMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link Query} contains named parameters.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public static boolean hasNamedParameter(Query query) {
|
||||
|
||||
for (Parameter<?> parameter : query.getParameters()) {
|
||||
if (parameter.getName() != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the given {@link Sort} into {@link javax.persistence.criteria.Order}s.
|
||||
*
|
||||
* @param sort
|
||||
* @param root
|
||||
* @param cb
|
||||
* @return
|
||||
*/
|
||||
public static List<javax.persistence.criteria.Order> toOrders(Sort sort, Root<?> root, CriteriaBuilder cb) {
|
||||
|
||||
List<javax.persistence.criteria.Order> orders = new ArrayList<javax.persistence.criteria.Order>();
|
||||
|
||||
if (sort == null) {
|
||||
return orders;
|
||||
}
|
||||
|
||||
for (org.springframework.data.domain.Sort.Order order : sort) {
|
||||
orders.add(toJpaOrder(order, root, cb));
|
||||
}
|
||||
|
||||
return orders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criteria API {@link javax.persistence.criteria.Order} from the given {@link Order}.
|
||||
*
|
||||
* @param order
|
||||
* @param root
|
||||
* @param cb
|
||||
* @return
|
||||
*/
|
||||
private static javax.persistence.criteria.Order toJpaOrder(Order order, Root<?> root, CriteriaBuilder cb) {
|
||||
|
||||
Expression<?> expression = null;
|
||||
String pathString = order.getProperty();
|
||||
String[] pathElements = pathString.split("\\.");
|
||||
int pathSize = pathElements.length;
|
||||
|
||||
if (pathSize > 1) {
|
||||
Join<Object, Object> path = root.join(pathElements[0]);
|
||||
for (int i = 1; i < pathSize - 1; i++) {
|
||||
path = path.join(pathElements[i]);
|
||||
}
|
||||
expression = path.get(pathElements[pathSize - 1]);
|
||||
} else {
|
||||
expression = root.get(pathString);
|
||||
}
|
||||
|
||||
return order.isAscending() ? cb.asc(expression) : cb.desc(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,117 +29,99 @@ import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
|
||||
/**
|
||||
* {@link RepositoryQuery} implementation that inspects a {@link QueryMethod}
|
||||
* for the existanve of an {@link org.springframework.data.jpa.repository.Query}
|
||||
* annotation and creates a JPA {@link Query} from it.
|
||||
* {@link RepositoryQuery} implementation that inspects a {@link QueryMethod} for the existanve of an
|
||||
* {@link org.springframework.data.jpa.repository.Query} annotation and creates a JPA {@link Query} from it.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
final class SimpleJpaQuery extends AbstractJpaQuery {
|
||||
|
||||
private static final Logger LOG = LoggerFactory
|
||||
.getLogger(SimpleJpaQuery.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SimpleJpaQuery.class);
|
||||
|
||||
private final String queryString;
|
||||
private final String countQuery;
|
||||
private final String alias;
|
||||
private final List<QueryHint> hints;
|
||||
private final Parameters parameters;
|
||||
private final String queryString;
|
||||
private final String countQuery;
|
||||
private final String alias;
|
||||
private final List<QueryHint> hints;
|
||||
private final Parameters parameters;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleJpaQuery} that encapsulates a simple query string.
|
||||
*/
|
||||
SimpleJpaQuery(JpaQueryMethod method, EntityManager em, String queryString) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleJpaQuery} that encapsulates a simple query
|
||||
* string.
|
||||
*/
|
||||
SimpleJpaQuery(JpaQueryMethod method, EntityManager em, String queryString) {
|
||||
super(method, em);
|
||||
this.queryString = queryString;
|
||||
this.alias = QueryUtils.detectAlias(queryString);
|
||||
this.hints = method.getHints();
|
||||
this.parameters = method.getParameters();
|
||||
this.countQuery = method.getCountQuery() == null ? QueryUtils.createCountQueryFor(queryString) : method
|
||||
.getCountQuery();
|
||||
|
||||
super(method, em);
|
||||
this.queryString = queryString;
|
||||
this.alias = QueryUtils.detectAlias(queryString);
|
||||
this.hints = method.getHints();
|
||||
this.parameters = method.getParameters();
|
||||
this.countQuery =
|
||||
method.getCountQuery() == null ? QueryUtils
|
||||
.createCountQueryFor(queryString) : method
|
||||
.getCountQuery();
|
||||
// Try to create a
|
||||
em.createQuery(queryString);
|
||||
}
|
||||
|
||||
// Try to create a
|
||||
em.createQuery(queryString);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.AbstractStringBasedJpaQuery
|
||||
* #
|
||||
* createQuery(org.springframework.data.jpa.repository.query.ParameterBinder
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public Query createQuery(Object[] values) {
|
||||
|
||||
ParameterAccessor accessor = new ParametersParameterAccessor(parameters, values);
|
||||
String sortedQueryString = QueryUtils.applySorting(queryString, accessor.getSort(), alias);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.AbstractStringBasedJpaQuery
|
||||
* #
|
||||
* createQuery(org.springframework.data.jpa.repository.query.ParameterBinder
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public Query createQuery(Object[] values) {
|
||||
Query query = getEntityManager().createQuery(sortedQueryString);
|
||||
return createBinder(values).bindAndPrepare(applyHints(query));
|
||||
}
|
||||
|
||||
ParameterAccessor accessor =
|
||||
new ParametersParameterAccessor(parameters, values);
|
||||
String sortedQueryString =
|
||||
QueryUtils.applySorting(queryString, accessor.getSort(), alias);
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.query.AbstractJpaQuery#
|
||||
* createCountQuery(java.lang.Object[])
|
||||
*/
|
||||
@Override
|
||||
protected Query createCountQuery(Object[] values) {
|
||||
|
||||
Query query = getEntityManager().createQuery(sortedQueryString);
|
||||
return createBinder(values).bindAndPrepare(applyHints(query));
|
||||
}
|
||||
return createBinder(values).bind(applyHints(getEntityManager().createQuery(countQuery)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the declared query hints to the given query.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
private Query applyHints(Query query) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.query.AbstractJpaQuery#
|
||||
* createCountQuery(java.lang.Object[])
|
||||
*/
|
||||
@Override
|
||||
protected Query createCountQuery(Object[] values) {
|
||||
for (QueryHint hint : hints) {
|
||||
query.setHint(hint.name(), hint.value());
|
||||
}
|
||||
|
||||
return createBinder(values).bind(
|
||||
applyHints(getEntityManager().createQuery(countQuery)));
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RepositoryQuery} from the given {@link QueryMethod} that is potentially annotated with
|
||||
* {@link org.springframework.data.jpa.repository.Query}.
|
||||
*
|
||||
* @param queryMethod
|
||||
* @param em
|
||||
* @return the {@link RepositoryQuery} derived from the annotation or {@code null} if no annotation found.
|
||||
*/
|
||||
public static RepositoryQuery fromQueryAnnotation(JpaQueryMethod queryMethod, EntityManager em) {
|
||||
|
||||
/**
|
||||
* Applies the declared query hints to the given query.
|
||||
*
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
private Query applyHints(Query query) {
|
||||
LOG.debug("Looking up query for method {}", queryMethod.getName());
|
||||
|
||||
for (QueryHint hint : hints) {
|
||||
query.setHint(hint.name(), hint.value());
|
||||
}
|
||||
String query = queryMethod.getAnnotatedQuery();
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link RepositoryQuery} from the given {@link QueryMethod} that
|
||||
* is potentially annotated with
|
||||
* {@link org.springframework.data.jpa.repository.Query}.
|
||||
*
|
||||
* @param queryMethod
|
||||
* @param em
|
||||
* @return the {@link RepositoryQuery} derived from the annotation or
|
||||
* {@code null} if no annotation found.
|
||||
*/
|
||||
public static RepositoryQuery fromQueryAnnotation(
|
||||
JpaQueryMethod queryMethod, EntityManager em) {
|
||||
|
||||
LOG.debug("Looking up query for method {}", queryMethod.getName());
|
||||
|
||||
String query = queryMethod.getAnnotatedQuery();
|
||||
|
||||
return query == null ? null
|
||||
: new SimpleJpaQuery(queryMethod, em, query);
|
||||
}
|
||||
return query == null ? null : new SimpleJpaQuery(queryMethod, em, query);
|
||||
}
|
||||
}
|
||||
@@ -21,28 +21,24 @@ import javax.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
|
||||
|
||||
/**
|
||||
* Extension of {@link EntityInformation} to capture aditional JPA specific
|
||||
* information about entities.
|
||||
* Extension of {@link EntityInformation} to capture aditional JPA specific information about entities.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface JpaEntityInformation<T, ID extends Serializable> extends
|
||||
EntityInformation<T, ID> {
|
||||
public interface JpaEntityInformation<T, ID extends Serializable> extends EntityInformation<T, ID> {
|
||||
|
||||
/**
|
||||
* Returns the id attribute of the entity.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
SingularAttribute<? super T, ?> getIdAttribute();
|
||||
/**
|
||||
* Returns the id attribute of the entity.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
SingularAttribute<? super T, ?> getIdAttribute();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the JPA entity name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getEntityName();
|
||||
/**
|
||||
* Returns the JPA entity name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getEntityName();
|
||||
}
|
||||
|
||||
@@ -25,68 +25,60 @@ import org.springframework.data.domain.Persistable;
|
||||
import org.springframework.data.repository.core.support.AbstractEntityInformation;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Base class for {@link JpaEntityInformation} implementations to share common
|
||||
* method implementations.
|
||||
* Base class for {@link JpaEntityInformation} implementations to share common method implementations.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class JpaEntityInformationSupport<T, ID extends Serializable>
|
||||
extends AbstractEntityInformation<T, ID> implements
|
||||
JpaEntityInformation<T, ID> {
|
||||
public abstract class JpaEntityInformationSupport<T, ID extends Serializable> extends AbstractEntityInformation<T, ID>
|
||||
implements JpaEntityInformation<T, ID> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaEntityInformationSupport} with the given domain
|
||||
* class.
|
||||
*
|
||||
* @param domainClass
|
||||
*/
|
||||
public JpaEntityInformationSupport(Class<T> domainClass) {
|
||||
/**
|
||||
* Creates a new {@link JpaEntityInformationSupport} with the given domain class.
|
||||
*
|
||||
* @param domainClass
|
||||
*/
|
||||
public JpaEntityInformationSupport(Class<T> domainClass) {
|
||||
|
||||
super(domainClass);
|
||||
}
|
||||
super(domainClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link JpaEntityInformation} for the given domain class and {@link EntityManager}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param em
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static <T> JpaEntityInformation<T, ?> getMetadata(Class<T> domainClass, EntityManager em) {
|
||||
|
||||
/**
|
||||
* Creates a {@link JpaEntityInformation} for the given domain class and
|
||||
* {@link EntityManager}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param em
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static <T> JpaEntityInformation<T, ?> getMetadata(
|
||||
Class<T> domainClass, EntityManager em) {
|
||||
Metamodel metamodel = em.getMetamodel();
|
||||
|
||||
Metamodel metamodel = em.getMetamodel();
|
||||
if (Persistable.class.isAssignableFrom(domainClass)) {
|
||||
return new JpaPersistableEntityInformation(domainClass, metamodel);
|
||||
} else {
|
||||
try {
|
||||
return new JpaMetamodelEntityInformation(domainClass, metamodel);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Persistable.class.isAssignableFrom(domainClass)) {
|
||||
return new JpaPersistableEntityInformation(domainClass, metamodel);
|
||||
} else {
|
||||
try {
|
||||
return new JpaMetamodelEntityInformation(domainClass, metamodel);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.JpaEntityInformation#
|
||||
* getEntityName()
|
||||
*/
|
||||
public String getEntityName() {
|
||||
|
||||
Class<?> domainClass = getJavaType();
|
||||
Entity entity = domainClass.getAnnotation(Entity.class);
|
||||
boolean hasName = null != entity && StringUtils.hasText(entity.name());
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.JpaEntityInformation#
|
||||
* getEntityName()
|
||||
*/
|
||||
public String getEntityName() {
|
||||
|
||||
Class<?> domainClass = getJavaType();
|
||||
Entity entity = domainClass.getAnnotation(Entity.class);
|
||||
boolean hasName = null != entity && StringUtils.hasText(entity.name());
|
||||
|
||||
return hasName ? entity.name() : domainClass.getSimpleName();
|
||||
}
|
||||
return hasName ? entity.name() : domainClass.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,104 +28,91 @@ import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@link EntityInformation} that uses JPA {@link Metamodel}
|
||||
* to find the domain class' id field.
|
||||
* Implementation of {@link EntityInformation} that uses JPA {@link Metamodel} to find the domain class' id field.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends
|
||||
JpaEntityInformationSupport<T, ID> implements
|
||||
JpaEntityInformation<T, ID> {
|
||||
public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends JpaEntityInformationSupport<T, ID>
|
||||
implements JpaEntityInformation<T, ID> {
|
||||
|
||||
private final SingularAttribute<? super T, ?> attribute;
|
||||
private final SingularAttribute<? super T, ?> attribute;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaMetamodelEntityInformation} for the given domain class and {@link Metamodel}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param metamodel
|
||||
*/
|
||||
public JpaMetamodelEntityInformation(Class<T> domainClass, Metamodel metamodel) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaMetamodelEntityInformation} for the given domain
|
||||
* class and {@link Metamodel}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param metamodel
|
||||
*/
|
||||
public JpaMetamodelEntityInformation(Class<T> domainClass,
|
||||
Metamodel metamodel) {
|
||||
super(domainClass);
|
||||
|
||||
super(domainClass);
|
||||
Assert.notNull(metamodel);
|
||||
EntityType<T> type = metamodel.entity(domainClass);
|
||||
|
||||
Assert.notNull(metamodel);
|
||||
EntityType<T> type = metamodel.entity(domainClass);
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("The given domain class can not be found in the given Metamodel!");
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"The given domain class can not be found in the given Metamodel!");
|
||||
}
|
||||
this.attribute = type.getId(type.getIdType().getJavaType());
|
||||
}
|
||||
|
||||
this.attribute = type.getId(type.getIdType().getJavaType());
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.IdAware#getId(java.lang.Object
|
||||
* )
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ID getId(T entity) {
|
||||
|
||||
return (ID) getMemberValue(attribute.getJavaMember(), entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.IdAware#getId(java.lang.Object
|
||||
* )
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ID getId(T entity) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.EntityInformation#getIdType()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<ID> getIdType() {
|
||||
|
||||
return (ID) getMemberValue(attribute.getJavaMember(), entity);
|
||||
}
|
||||
return (Class<ID>) attribute.getJavaType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the given {@link Member} of the given {@link Object} .
|
||||
*
|
||||
* @param member
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private static Object getMemberValue(Member member, Object source) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.EntityInformation#getIdType()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<ID> getIdType() {
|
||||
if (member instanceof Field) {
|
||||
Field field = (Field) member;
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return ReflectionUtils.getField(field, source);
|
||||
} else if (member instanceof Method) {
|
||||
Method method = (Method) member;
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
return ReflectionUtils.invokeMethod(method, source);
|
||||
}
|
||||
|
||||
return (Class<ID>) attribute.getJavaType();
|
||||
}
|
||||
throw new IllegalArgumentException("Given member is neither Field nor Method!");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.support.JpaEntityMetadata#
|
||||
* getIdAttribute()
|
||||
*/
|
||||
public SingularAttribute<? super T, ?> getIdAttribute() {
|
||||
|
||||
/**
|
||||
* Returns the value of the given {@link Member} of the given {@link Object}
|
||||
* .
|
||||
*
|
||||
* @param member
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private static Object getMemberValue(Member member, Object source) {
|
||||
|
||||
if (member instanceof Field) {
|
||||
Field field = (Field) member;
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return ReflectionUtils.getField(field, source);
|
||||
} else if (member instanceof Method) {
|
||||
Method method = (Method) member;
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
return ReflectionUtils.invokeMethod(method, source);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"Given member is neither Field nor Method!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.support.JpaEntityMetadata#
|
||||
* getIdAttribute()
|
||||
*/
|
||||
public SingularAttribute<? super T, ?> getIdAttribute() {
|
||||
|
||||
return attribute;
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,54 +21,48 @@ import javax.persistence.metamodel.Metamodel;
|
||||
|
||||
import org.springframework.data.domain.Persistable;
|
||||
|
||||
|
||||
/**
|
||||
* Extension of {@link JpaMetamodelEntityInformation} that consideres methods of
|
||||
* {@link Persistable} to lookup the id.
|
||||
* Extension of {@link JpaMetamodelEntityInformation} that consideres methods of {@link Persistable} to lookup the id.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JpaPersistableEntityInformation<T extends Persistable<ID>, ID extends Serializable>
|
||||
extends JpaMetamodelEntityInformation<T, ID> {
|
||||
public class JpaPersistableEntityInformation<T extends Persistable<ID>, ID extends Serializable> extends
|
||||
JpaMetamodelEntityInformation<T, ID> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaPersistableEntityInformation} for the given
|
||||
* domain class and {@link Metamodel}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param metamodel
|
||||
*/
|
||||
public JpaPersistableEntityInformation(Class<T> domainClass,
|
||||
Metamodel metamodel) {
|
||||
/**
|
||||
* Creates a new {@link JpaPersistableEntityInformation} for the given domain class and {@link Metamodel}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param metamodel
|
||||
*/
|
||||
public JpaPersistableEntityInformation(Class<T> domainClass, Metamodel metamodel) {
|
||||
|
||||
super(domainClass, metamodel);
|
||||
}
|
||||
super(domainClass, metamodel);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.AbstractEntityInformation
|
||||
* #isNew(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean isNew(T entity) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.AbstractEntityInformation
|
||||
* #isNew(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean isNew(T entity) {
|
||||
return entity.isNew();
|
||||
}
|
||||
|
||||
return entity.isNew();
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.JpaMetamodelEntityMetadata
|
||||
* #getId(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public ID getId(T entity) {
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.JpaMetamodelEntityMetadata
|
||||
* #getId(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public ID getId(T entity) {
|
||||
|
||||
return entity.getId();
|
||||
}
|
||||
return entity.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* JPA specific generic repository factory.
|
||||
*
|
||||
@@ -39,124 +38,110 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class JpaRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final EntityManager entityManager;
|
||||
private final QueryExtractor extractor;
|
||||
private final EntityManager entityManager;
|
||||
private final QueryExtractor extractor;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaRepositoryFactory}.
|
||||
*
|
||||
* @param entityManager must not be {@literal null}
|
||||
*/
|
||||
public JpaRepositoryFactory(EntityManager entityManager) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaRepositoryFactory}.
|
||||
*
|
||||
* @param entityManager must not be {@literal null}
|
||||
*/
|
||||
public JpaRepositoryFactory(EntityManager entityManager) {
|
||||
Assert.notNull(entityManager);
|
||||
this.entityManager = entityManager;
|
||||
this.extractor = PersistenceProvider.fromEntityManager(entityManager);
|
||||
}
|
||||
|
||||
Assert.notNull(entityManager);
|
||||
this.entityManager = entityManager;
|
||||
this.extractor = PersistenceProvider.fromEntityManager(entityManager);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getTargetRepository(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryMetadata metadata) {
|
||||
|
||||
return getTargetRepository(metadata, entityManager);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getTargetRepository(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryMetadata metadata) {
|
||||
/**
|
||||
* Callback to create a {@link JpaRepository} instance with the given {@link EntityManager}
|
||||
*
|
||||
* @param <T>
|
||||
* @param <ID>
|
||||
* @param entityManager
|
||||
* @see #getTargetRepository(RepositoryMetadata)
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata,
|
||||
EntityManager entityManager) {
|
||||
|
||||
return getTargetRepository(metadata, entityManager);
|
||||
}
|
||||
Class<?> repositoryInterface = metadata.getRepositoryInterface();
|
||||
JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainClass());
|
||||
|
||||
if (isQueryDslExecutor(repositoryInterface)) {
|
||||
return new QueryDslJpaRepository(entityInformation, entityManager);
|
||||
} else {
|
||||
return new SimpleJpaRepository(entityInformation, entityManager);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to create a {@link JpaRepository} instance with the given
|
||||
* {@link EntityManager}
|
||||
*
|
||||
* @param <T>
|
||||
* @param <ID>
|
||||
* @param entityManager
|
||||
* @see #getTargetRepository(RepositoryMetadata)
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository(
|
||||
RepositoryMetadata metadata, EntityManager entityManager) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getRepositoryBaseClass()
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
|
||||
Class<?> repositoryInterface = metadata.getRepositoryInterface();
|
||||
JpaEntityInformation<?, Serializable> entityInformation =
|
||||
getEntityInformation(metadata.getDomainClass());
|
||||
if (isQueryDslExecutor(metadata.getRepositoryInterface())) {
|
||||
return QueryDslJpaRepository.class;
|
||||
} else {
|
||||
return SimpleJpaRepository.class;
|
||||
}
|
||||
}
|
||||
|
||||
if (isQueryDslExecutor(repositoryInterface)) {
|
||||
return new QueryDslJpaRepository(entityInformation, entityManager);
|
||||
} else {
|
||||
return new SimpleJpaRepository(entityInformation, entityManager);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns whether the given repository interface requires a QueryDsl specific implementation to be chosen.
|
||||
*
|
||||
* @param repositoryInterface
|
||||
* @return
|
||||
*/
|
||||
private boolean isQueryDslExecutor(Class<?> repositoryInterface) {
|
||||
|
||||
return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getRepositoryBaseClass()
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getQueryLookupStrategy
|
||||
* (org.springframework.data.repository.query.QueryLookupStrategy.Key)
|
||||
*/
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
|
||||
|
||||
if (isQueryDslExecutor(metadata.getRepositoryInterface())) {
|
||||
return QueryDslJpaRepository.class;
|
||||
} else {
|
||||
return SimpleJpaRepository.class;
|
||||
}
|
||||
}
|
||||
return JpaQueryLookupStrategy.create(entityManager, key, extractor);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> JpaEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
|
||||
/**
|
||||
* Returns whether the given repository interface requires a QueryDsl
|
||||
* specific implementation to be chosen.
|
||||
*
|
||||
* @param repositoryInterface
|
||||
* @return
|
||||
*/
|
||||
private boolean isQueryDslExecutor(Class<?> repositoryInterface) {
|
||||
|
||||
return QUERY_DSL_PRESENT
|
||||
&& QueryDslPredicateExecutor.class
|
||||
.isAssignableFrom(repositoryInterface);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getQueryLookupStrategy
|
||||
* (org.springframework.data.repository.query.QueryLookupStrategy.Key)
|
||||
*/
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
|
||||
|
||||
return JpaQueryLookupStrategy.create(entityManager, key, extractor);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> JpaEntityInformation<T, ID> getEntityInformation(
|
||||
Class<T> domainClass) {
|
||||
|
||||
return (JpaEntityInformation<T, ID>) JpaEntityInformationSupport
|
||||
.getMetadata(domainClass, entityManager);
|
||||
}
|
||||
return (JpaEntityInformation<T, ID>) JpaEntityInformationSupport.getMetadata(domainClass, entityManager);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,69 +26,63 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport
|
||||
import org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Special adapter for Springs {@link FactoryBean} interface to allow easy setup
|
||||
* of repository factories via Spring configuration.
|
||||
* Special adapter for Springs {@link FactoryBean} interface to allow easy setup of repository factories via Spring
|
||||
* configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Eberhard Wolff
|
||||
* @param <T> the type of the repository
|
||||
*/
|
||||
public class JpaRepositoryFactoryBean<T extends JpaRepository<S, ID>, S, ID extends Serializable>
|
||||
extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
|
||||
public class JpaRepositoryFactoryBean<T extends JpaRepository<S, ID>, S, ID extends Serializable> extends
|
||||
TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
|
||||
|
||||
private EntityManager entityManager;
|
||||
private EntityManager entityManager;
|
||||
|
||||
/**
|
||||
* The {@link EntityManager} to be used.
|
||||
*
|
||||
* @param entityManager the entityManager to set
|
||||
*/
|
||||
@PersistenceContext
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
|
||||
/**
|
||||
* The {@link EntityManager} to be used.
|
||||
*
|
||||
* @param entityManager the entityManager to set
|
||||
*/
|
||||
@PersistenceContext
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.support.
|
||||
* TransactionalRepositoryFactoryBeanSupport#doCreateRepositoryFactory()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryFactorySupport doCreateRepositoryFactory() {
|
||||
|
||||
return createRepositoryFactory(entityManager);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.support.
|
||||
* TransactionalRepositoryFactoryBeanSupport#doCreateRepositoryFactory()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryFactorySupport doCreateRepositoryFactory() {
|
||||
/**
|
||||
* Returns a {@link RepositoryFactorySupport}.
|
||||
*
|
||||
* @param entityManager
|
||||
* @return
|
||||
*/
|
||||
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
|
||||
|
||||
return createRepositoryFactory(entityManager);
|
||||
}
|
||||
return new JpaRepositoryFactory(entityManager);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
/**
|
||||
* Returns a {@link RepositoryFactorySupport}.
|
||||
*
|
||||
* @param entityManager
|
||||
* @return
|
||||
*/
|
||||
protected RepositoryFactorySupport createRepositoryFactory(
|
||||
EntityManager entityManager) {
|
||||
|
||||
return new JpaRepositoryFactory(entityManager);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
Assert.notNull(entityManager, "EntityManager must not be null!");
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
Assert.notNull(entityManager, "EntityManager must not be null!");
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.eclipse.persistence.jpa.JpaQuery;
|
||||
import org.hibernate.ejb.HibernateQuery;
|
||||
import org.springframework.data.jpa.repository.query.QueryExtractor;
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration representing peristence providers to be used.
|
||||
*
|
||||
@@ -33,129 +32,119 @@ import org.springframework.data.jpa.repository.query.QueryExtractor;
|
||||
*/
|
||||
public enum PersistenceProvider implements QueryExtractor {
|
||||
|
||||
/**
|
||||
* Hibernate persistence provider.
|
||||
*/
|
||||
HIBERNATE("org.hibernate.ejb.HibernateEntityManager") {
|
||||
/**
|
||||
* Hibernate persistence provider.
|
||||
*/
|
||||
HIBERNATE("org.hibernate.ejb.HibernateEntityManager") {
|
||||
|
||||
public String extractQueryString(Query query) {
|
||||
public String extractQueryString(Query query) {
|
||||
|
||||
return ((HibernateQuery) query).getHibernateQuery()
|
||||
.getQueryString();
|
||||
}
|
||||
return ((HibernateQuery) query).getHibernateQuery().getQueryString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return custom placeholder ({@code *}) as Hibernate does create invalid queries for count queries for objects with
|
||||
* compound keys.
|
||||
*
|
||||
* @see HHH-4044
|
||||
* @see HHH-3096
|
||||
*/
|
||||
@Override
|
||||
protected String getCountQueryPlaceholder() {
|
||||
|
||||
/**
|
||||
* Return custom placeholder ({@code *}) as Hibernate does create
|
||||
* invalid queries for count queries for objects with compound keys.
|
||||
*
|
||||
* @see HHH-4044
|
||||
* @see HHH-3096
|
||||
*/
|
||||
@Override
|
||||
protected String getCountQueryPlaceholder() {
|
||||
return "*";
|
||||
}
|
||||
},
|
||||
|
||||
return "*";
|
||||
}
|
||||
},
|
||||
/**
|
||||
* EclipseLink persistence provider.
|
||||
*/
|
||||
ECLIPSELINK("org.eclipse.persistence.jpa.JpaEntityManager") {
|
||||
|
||||
/**
|
||||
* EclipseLink persistence provider.
|
||||
*/
|
||||
ECLIPSELINK("org.eclipse.persistence.jpa.JpaEntityManager") {
|
||||
public String extractQueryString(Query query) {
|
||||
|
||||
public String extractQueryString(Query query) {
|
||||
return ((JpaQuery<?>) query).getDatabaseQuery().getJPQLString();
|
||||
}
|
||||
|
||||
return ((JpaQuery<?>) query).getDatabaseQuery().getJPQLString();
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
/**
|
||||
* OpenJpa persistence provider.
|
||||
*/
|
||||
OPEN_JPA("org.apache.openjpa.persistence.OpenJPAEntityManager") {
|
||||
|
||||
/**
|
||||
* OpenJpa persistence provider.
|
||||
*/
|
||||
OPEN_JPA("org.apache.openjpa.persistence.OpenJPAEntityManager") {
|
||||
public String extractQueryString(Query query) {
|
||||
|
||||
public String extractQueryString(Query query) {
|
||||
return ((OpenJPAQuery<?>) query).getQueryString();
|
||||
}
|
||||
},
|
||||
|
||||
return ((OpenJPAQuery<?>) query).getQueryString();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Unknown special provider. Use standard JPA.
|
||||
*/
|
||||
GENERIC_JPA("javax.persistence.EntityManager") {
|
||||
|
||||
/**
|
||||
* Unknown special provider. Use standard JPA.
|
||||
*/
|
||||
GENERIC_JPA("javax.persistence.EntityManager") {
|
||||
public String extractQueryString(Query query) {
|
||||
|
||||
public String extractQueryString(Query query) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public boolean canExtractQuery() {
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean canExtractQuery() {
|
||||
private String entityManagerClassName;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Creates a new {@link PersistenceProvider}.
|
||||
*
|
||||
* @param entityManagerClassName the name of the provider specific {@link EntityManager} implementation
|
||||
*/
|
||||
private PersistenceProvider(String entityManagerClassName) {
|
||||
|
||||
private String entityManagerClassName;
|
||||
this.entityManagerClassName = entityManagerClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the {@link PersistenceProvider} from the given {@link EntityManager}. If no special one can be
|
||||
* determined {@value #GENERIC_JPA} will be returned.
|
||||
*
|
||||
* @param em
|
||||
* @return
|
||||
*/
|
||||
public static PersistenceProvider fromEntityManager(EntityManager em) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link PersistenceProvider}.
|
||||
*
|
||||
* @param entityManagerClassName the name of the provider specific
|
||||
* {@link EntityManager} implementation
|
||||
*/
|
||||
private PersistenceProvider(String entityManagerClassName) {
|
||||
for (PersistenceProvider provider : values()) {
|
||||
if (isEntityManagerOfType(em, provider.entityManagerClassName)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
|
||||
this.entityManagerClassName = entityManagerClassName;
|
||||
}
|
||||
return GENERIC_JPA;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.QueryExtractor#canExtractQuery
|
||||
* ()
|
||||
*/
|
||||
public boolean canExtractQuery() {
|
||||
|
||||
/**
|
||||
* Determines the {@link PersistenceProvider} from the given
|
||||
* {@link EntityManager}. If no special one can be determined
|
||||
* {@value #GENERIC_JPA} will be returned.
|
||||
*
|
||||
* @param em
|
||||
* @return
|
||||
*/
|
||||
public static PersistenceProvider fromEntityManager(EntityManager em) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (PersistenceProvider provider : values()) {
|
||||
if (isEntityManagerOfType(em, provider.entityManagerClassName)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the placeholder to be used for simple count queries. Default implementation returns {@code *}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected String getCountQueryPlaceholder() {
|
||||
|
||||
return GENERIC_JPA;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.query.QueryExtractor#canExtractQuery
|
||||
* ()
|
||||
*/
|
||||
public boolean canExtractQuery() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the placeholder to be used for simple count queries. Default
|
||||
* implementation returns {@code *}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected String getCountQueryPlaceholder() {
|
||||
|
||||
return "x";
|
||||
}
|
||||
return "x";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,191 +37,172 @@ import com.mysema.query.types.OrderSpecifier;
|
||||
import com.mysema.query.types.Predicate;
|
||||
import com.mysema.query.types.path.PathBuilder;
|
||||
|
||||
|
||||
/**
|
||||
* QueryDsl specific extension of {@link SimpleJpaRepository} which adds
|
||||
* implementation for {@link QueryDslPredicateExecutor}.
|
||||
* QueryDsl specific extension of {@link SimpleJpaRepository} which adds implementation for
|
||||
* {@link QueryDslPredicateExecutor}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class QueryDslJpaRepository<T, ID extends Serializable> extends
|
||||
SimpleJpaRepository<T, ID> implements QueryDslPredicateExecutor<T> {
|
||||
public class QueryDslJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements
|
||||
QueryDslPredicateExecutor<T> {
|
||||
|
||||
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER =
|
||||
SimpleEntityPathResolver.INSTANCE;
|
||||
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
|
||||
|
||||
private final EntityManager em;
|
||||
private final EntityPath<T> path;
|
||||
private final PathBuilder<T> builder;
|
||||
private final EntityManager em;
|
||||
private final EntityPath<T> path;
|
||||
private final PathBuilder<T> builder;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QueryDslJpaRepository} from the given domain class and {@link EntityManager}. This will use
|
||||
* the {@link SimpleEntityPathResolver} to translate the given domain class into an {@link EntityPath}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param entityManager
|
||||
*/
|
||||
public QueryDslJpaRepository(JpaEntityInformation<T, ID> entityMetadata, EntityManager entityManager) {
|
||||
|
||||
/**
|
||||
* Creates a new {@link QueryDslJpaRepository} from the given domain class
|
||||
* and {@link EntityManager}. This will use the
|
||||
* {@link SimpleEntityPathResolver} to translate the given domain class into
|
||||
* an {@link EntityPath}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param entityManager
|
||||
*/
|
||||
public QueryDslJpaRepository(JpaEntityInformation<T, ID> entityMetadata,
|
||||
EntityManager entityManager) {
|
||||
this(entityMetadata, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
|
||||
}
|
||||
|
||||
this(entityMetadata, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
|
||||
}
|
||||
/**
|
||||
* Creates a new {@link QueryDslJpaRepository} from the given domain class and {@link EntityManager} and uses the
|
||||
* given {@link EntityPathResolver} to translate the domain class into an {@link EntityPath}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param entityManager
|
||||
* @param resolver
|
||||
*/
|
||||
public QueryDslJpaRepository(JpaEntityInformation<T, ID> entityMetadata, EntityManager entityManager,
|
||||
EntityPathResolver resolver) {
|
||||
|
||||
super(entityMetadata, entityManager);
|
||||
this.em = entityManager;
|
||||
this.path = resolver.createPath(entityMetadata.getJavaType());
|
||||
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link QueryDslJpaRepository} from the given domain class
|
||||
* and {@link EntityManager} and uses the given {@link EntityPathResolver}
|
||||
* to translate the domain class into an {@link EntityPath}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param entityManager
|
||||
* @param resolver
|
||||
*/
|
||||
public QueryDslJpaRepository(JpaEntityInformation<T, ID> entityMetadata,
|
||||
EntityManager entityManager, EntityPathResolver resolver) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#findOne(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
public T findOne(Predicate predicate) {
|
||||
|
||||
super(entityMetadata, entityManager);
|
||||
this.em = entityManager;
|
||||
this.path = resolver.createPath(entityMetadata.getJavaType());
|
||||
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
|
||||
}
|
||||
return createQuery(predicate).uniqueResult(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#findAll(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
public List<T> findAll(Predicate predicate) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#findOne(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
public T findOne(Predicate predicate) {
|
||||
return createQuery(predicate).list(path);
|
||||
}
|
||||
|
||||
return createQuery(predicate).uniqueResult(path);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#findAll(com.mysema.query.types.Predicate,
|
||||
* com.mysema.query.types.OrderSpecifier<?>[])
|
||||
*/
|
||||
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
|
||||
|
||||
return createQuery(predicate).orderBy(orders).list(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#findAll(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
public List<T> findAll(Predicate predicate) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#findAll(com.mysema.query.types.Predicate,
|
||||
* org.springframework.data.domain.Pageable)
|
||||
*/
|
||||
public Page<T> findAll(Predicate predicate, Pageable pageable) {
|
||||
|
||||
return createQuery(predicate).list(path);
|
||||
}
|
||||
JPQLQuery countQuery = createQuery(predicate);
|
||||
JPQLQuery query = applyPagination(createQuery(predicate), pageable);
|
||||
|
||||
return new PageImpl<T>(query.list(path), pageable, countQuery.count());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#findAll(com.mysema.query.types.Predicate,
|
||||
* com.mysema.query.types.OrderSpecifier<?>[])
|
||||
*/
|
||||
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#count(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
public long count(Predicate predicate) {
|
||||
|
||||
return createQuery(predicate).orderBy(orders).list(path);
|
||||
}
|
||||
return createQuery(predicate).count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link JPQLQuery} for the given {@link Predicate}.
|
||||
*
|
||||
* @param predicate
|
||||
* @return
|
||||
*/
|
||||
protected JPQLQuery createQuery(Predicate... predicate) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#findAll(com.mysema.query.types.Predicate,
|
||||
* org.springframework.data.domain.Pageable)
|
||||
*/
|
||||
public Page<T> findAll(Predicate predicate, Pageable pageable) {
|
||||
return new JPAQuery(em).from(path).where(predicate);
|
||||
}
|
||||
|
||||
JPQLQuery countQuery = createQuery(predicate);
|
||||
JPQLQuery query = applyPagination(createQuery(predicate), pageable);
|
||||
/**
|
||||
* Applies the given {@link Pageable} to the given {@link JPQLQuery}.
|
||||
*
|
||||
* @param query
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
protected JPQLQuery applyPagination(JPQLQuery query, Pageable pageable) {
|
||||
|
||||
return new PageImpl<T>(query.list(path), pageable, countQuery.count());
|
||||
}
|
||||
if (pageable == null) {
|
||||
return query;
|
||||
}
|
||||
|
||||
query.offset(pageable.getOffset());
|
||||
query.limit(pageable.getPageSize());
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.querydsl.
|
||||
* QueryDslSpecificationExecutor#count(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
public long count(Predicate predicate) {
|
||||
return applySorting(query, pageable.getSort());
|
||||
}
|
||||
|
||||
return createQuery(predicate).count();
|
||||
}
|
||||
/**
|
||||
* Applies sorting to the given {@link JPQLQuery}.
|
||||
*
|
||||
* @param query
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
protected JPQLQuery applySorting(JPQLQuery query, Sort sort) {
|
||||
|
||||
if (sort == null) {
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link JPQLQuery} for the given {@link Predicate}.
|
||||
*
|
||||
* @param predicate
|
||||
* @return
|
||||
*/
|
||||
protected JPQLQuery createQuery(Predicate... predicate) {
|
||||
for (Order order : sort) {
|
||||
query.orderBy(toOrder(order));
|
||||
}
|
||||
|
||||
return new JPAQuery(em).from(path).where(predicate);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a plain {@link Order} into a QueryDsl specific {@link OrderSpecifier}.
|
||||
*
|
||||
* @param order
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
protected OrderSpecifier<?> toOrder(Order order) {
|
||||
|
||||
/**
|
||||
* Applies the given {@link Pageable} to the given {@link JPQLQuery}.
|
||||
*
|
||||
* @param query
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
protected JPQLQuery applyPagination(JPQLQuery query, Pageable pageable) {
|
||||
Expression<Object> property = builder.get(order.getProperty());
|
||||
|
||||
if (pageable == null) {
|
||||
return query;
|
||||
}
|
||||
|
||||
query.offset(pageable.getOffset());
|
||||
query.limit(pageable.getPageSize());
|
||||
|
||||
return applySorting(query, pageable.getSort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies sorting to the given {@link JPQLQuery}.
|
||||
*
|
||||
* @param query
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
protected JPQLQuery applySorting(JPQLQuery query, Sort sort) {
|
||||
|
||||
if (sort == null) {
|
||||
return query;
|
||||
}
|
||||
|
||||
for (Order order : sort) {
|
||||
query.orderBy(toOrder(order));
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transforms a plain {@link Order} into a QueryDsl specific
|
||||
* {@link OrderSpecifier}.
|
||||
*
|
||||
* @param order
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
protected OrderSpecifier<?> toOrder(Order order) {
|
||||
|
||||
Expression<Object> property = builder.get(order.getProperty());
|
||||
|
||||
return new OrderSpecifier(
|
||||
order.isAscending() ? com.mysema.query.types.Order.ASC
|
||||
: com.mysema.query.types.Order.DESC, property);
|
||||
}
|
||||
return new OrderSpecifier(order.isAscending() ? com.mysema.query.types.Order.ASC
|
||||
: com.mysema.query.types.Order.DESC, property);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import com.mysema.query.types.EntityPath;
|
||||
import com.mysema.query.types.path.PathBuilder;
|
||||
import com.mysema.query.types.path.PathBuilderFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Base class for implementing repositories using QueryDsl library.
|
||||
*
|
||||
@@ -27,78 +26,72 @@ import com.mysema.query.types.path.PathBuilderFactory;
|
||||
@Repository
|
||||
public abstract class QueryDslRepositorySupport {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
private PathBuilderFactory builderFactory = new PathBuilderFactory();
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
private PathBuilderFactory builderFactory = new PathBuilderFactory();
|
||||
|
||||
/**
|
||||
* Setter to inject {@link EntityManager}.
|
||||
*
|
||||
* @param entityManager must not be {@literal null}
|
||||
*/
|
||||
@Required
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
|
||||
/**
|
||||
* Setter to inject {@link EntityManager}.
|
||||
*
|
||||
* @param entityManager must not be {@literal null}
|
||||
*/
|
||||
@Required
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
Assert.notNull(entityManager);
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
Assert.notNull(entityManager);
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
/**
|
||||
* Callback to verify configuration. Used by containers.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void validate() {
|
||||
|
||||
Assert.notNull(entityManager, "EntityManager must not be null!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to verify configuration. Used by containers.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void validate() {
|
||||
/**
|
||||
* Returns a fresh {@link JPQLQuery}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected JPQLQuery from(EntityPath<?>... paths) {
|
||||
|
||||
Assert.notNull(entityManager, "EntityManager must not be null!");
|
||||
}
|
||||
return new JPAQuery(entityManager).from(paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fresh {@link DeleteClause}.
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
protected DeleteClause<JPADeleteClause> delete(EntityPath<?> path) {
|
||||
|
||||
/**
|
||||
* Returns a fresh {@link JPQLQuery}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected JPQLQuery from(EntityPath<?>... paths) {
|
||||
return new JPADeleteClause(entityManager, path);
|
||||
}
|
||||
|
||||
return new JPAQuery(entityManager).from(paths);
|
||||
}
|
||||
/**
|
||||
* Returns a fresh {@link UpdateClause}.
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
protected UpdateClause<JPAUpdateClause> update(EntityPath<?> path) {
|
||||
|
||||
return new JPAUpdateClause(entityManager, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fresh {@link DeleteClause}.
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
protected DeleteClause<JPADeleteClause> delete(EntityPath<?> path) {
|
||||
/**
|
||||
* Returns a {@link PathBuilder} for the given type.
|
||||
*
|
||||
* @param <T>
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
protected <T> PathBuilder<T> getBuilder(Class<T> type) {
|
||||
|
||||
return new JPADeleteClause(entityManager, path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a fresh {@link UpdateClause}.
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
protected UpdateClause<JPAUpdateClause> update(EntityPath<?> path) {
|
||||
|
||||
return new JPAUpdateClause(entityManager, path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a {@link PathBuilder} for the given type.
|
||||
*
|
||||
* @param <T>
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
protected <T> PathBuilder<T> getBuilder(Class<T> type) {
|
||||
|
||||
return builderFactory.create(type);
|
||||
}
|
||||
return builderFactory.create(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,11 +40,9 @@ import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link CrudRepository} interface. This will
|
||||
* offer you a more sophisticated interface than the plain {@link EntityManager}
|
||||
* .
|
||||
* Default implementation of the {@link CrudRepository} interface. This will offer you a more sophisticated interface
|
||||
* than the plain {@link EntityManager} .
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Eberhard Wolff
|
||||
@@ -53,481 +51,437 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
@org.springframework.stereotype.Repository
|
||||
@Transactional(readOnly = true)
|
||||
public class SimpleJpaRepository<T, ID extends Serializable> implements
|
||||
JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
|
||||
|
||||
private final JpaEntityInformation<T, ?> entityInformation;
|
||||
private final EntityManager em;
|
||||
private final PersistenceProvider provider;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleJpaRepository} to manage objects of the given
|
||||
* {@link JpaEntityInformation}.
|
||||
*
|
||||
* @param entityInformation
|
||||
* @param entityManager
|
||||
*/
|
||||
public SimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation,
|
||||
EntityManager entityManager) {
|
||||
|
||||
Assert.notNull(entityInformation);
|
||||
Assert.notNull(entityManager);
|
||||
this.entityInformation = entityInformation;
|
||||
this.em = entityManager;
|
||||
this.provider = PersistenceProvider.fromEntityManager(entityManager);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleJpaRepository} to manage objects of the given
|
||||
* domain type.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param em
|
||||
*/
|
||||
public SimpleJpaRepository(Class<T> domainClass, EntityManager em) {
|
||||
|
||||
this(JpaEntityInformationSupport.getMetadata(domainClass, em), em);
|
||||
}
|
||||
|
||||
|
||||
private Class<T> getDomainClass() {
|
||||
|
||||
return entityInformation.getJavaType();
|
||||
}
|
||||
|
||||
|
||||
private String getDeleteAllQueryString() {
|
||||
|
||||
return getQueryString(DELETE_ALL_QUERY_STRING,
|
||||
entityInformation.getEntityName());
|
||||
}
|
||||
|
||||
|
||||
private String getCountQueryString() {
|
||||
|
||||
String countQuery =
|
||||
String.format(COUNT_QUERY_STRING,
|
||||
provider.getCountQueryPlaceholder(), "%s");
|
||||
|
||||
return getQueryString(countQuery, entityInformation.getEntityName());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaRepository#delete(java.io.
|
||||
* Serializable)
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(ID id) {
|
||||
|
||||
delete(findOne(id));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#delete(java.lang.Object)
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(T entity) {
|
||||
|
||||
em.remove(em.contains(entity) ? entity : em.merge(entity));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#delete(java.lang.Iterable)
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(Iterable<? extends T> entities) {
|
||||
|
||||
if (entities == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (T entity : entities) {
|
||||
delete(entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaRepository#deleteInBatch(java
|
||||
* .lang.Iterable)
|
||||
*/
|
||||
@Transactional
|
||||
public void deleteInBatch(Iterable<T> entities) {
|
||||
|
||||
if (null == entities || !entities.iterator().hasNext()) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyAndBind(
|
||||
getQueryString(DELETE_ALL_QUERY_STRING,
|
||||
entityInformation.getEntityName()), entities, em)
|
||||
.executeUpdate();
|
||||
em.clear();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#deleteAll()
|
||||
*/
|
||||
@Transactional
|
||||
public void deleteAll() {
|
||||
|
||||
em.createQuery(getDeleteAllQueryString()).executeUpdate();
|
||||
em.clear();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#readById(java.io.Serializable
|
||||
* )
|
||||
*/
|
||||
public T findOne(ID id) {
|
||||
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
return em.find(getDomainClass(), id);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#exists(java.io.Serializable
|
||||
* )
|
||||
*/
|
||||
public boolean exists(ID id) {
|
||||
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
return null != findOne(id);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#readAll()
|
||||
*/
|
||||
public List<T> findAll() {
|
||||
|
||||
return getQuery(null, (Sort) null).getResultList();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#readAll(org.springframework
|
||||
* .data.domain.Sort)
|
||||
*/
|
||||
public List<T> findAll(Sort sort) {
|
||||
|
||||
return getQuery(null, sort).getResultList();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#readAll(org.
|
||||
* springframework.data.domain.Pageable)
|
||||
*/
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
|
||||
if (null == pageable) {
|
||||
return new PageImpl<T>(findAll());
|
||||
}
|
||||
|
||||
return findAll(null, pageable);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.JpaRepository#findOneBy(org.
|
||||
* springframework.data.jpa.domain.Specification)
|
||||
*/
|
||||
public T findOne(Specification<T> spec) {
|
||||
|
||||
try {
|
||||
return getQuery(spec, (Sort) null).getSingleResult();
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.JpaRepository#readAll(org.
|
||||
* springframework.data.jpa.domain.Specification)
|
||||
*/
|
||||
public List<T> findAll(Specification<T> spec) {
|
||||
|
||||
return getQuery(spec, (Sort) null).getResultList();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.JpaRepository#readAll(org.
|
||||
* springframework.data.jpa.domain.Specification,
|
||||
* org.springframework.data.domain.Pageable)
|
||||
*/
|
||||
public Page<T> findAll(Specification<T> spec, Pageable pageable) {
|
||||
|
||||
TypedQuery<T> query = getQuery(spec, pageable);
|
||||
|
||||
return pageable == null ? new PageImpl<T>(query.getResultList())
|
||||
: readPage(query, pageable, spec);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaSpecificationExecutor#findAll
|
||||
* (org.springframework.data.jpa.domain.Specification,
|
||||
* org.springframework.data.domain.Sort)
|
||||
*/
|
||||
public List<T> findAll(Specification<T> spec, Sort sort) {
|
||||
|
||||
return getQuery(spec, sort).getResultList();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#count()
|
||||
*/
|
||||
public long count() {
|
||||
|
||||
return em.createQuery(getCountQueryString(), Long.class)
|
||||
.getSingleResult();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaSpecificationExecutor#count
|
||||
* (org.springframework.data.jpa.domain.Specification)
|
||||
*/
|
||||
public long count(Specification<T> spec) {
|
||||
|
||||
return getCountQuery(spec).getSingleResult();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#save(java.lang.Object)
|
||||
*/
|
||||
@Transactional
|
||||
public T save(T entity) {
|
||||
|
||||
if (entityInformation.isNew(entity)) {
|
||||
em.persist(entity);
|
||||
return entity;
|
||||
} else {
|
||||
return em.merge(entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaRepository#saveAndFlush(java
|
||||
* .lang.Object)
|
||||
*/
|
||||
@Transactional
|
||||
public T saveAndFlush(T entity) {
|
||||
|
||||
T result = save(entity);
|
||||
flush();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#save(java.lang.Iterable)
|
||||
*/
|
||||
@Transactional
|
||||
public List<T> save(Iterable<? extends T> entities) {
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
|
||||
if (entities == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (T entity : entities) {
|
||||
result.add(save(entity));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.JpaRepository#flush()
|
||||
*/
|
||||
@Transactional
|
||||
public void flush() {
|
||||
|
||||
em.flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the given {@link TypedQuery} into a {@link Page} applying the given
|
||||
* {@link Pageable} and {@link Specification}.
|
||||
*
|
||||
* @param query
|
||||
* @param spec
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
private Page<T> readPage(TypedQuery<T> query, Pageable pageable,
|
||||
Specification<T> spec) {
|
||||
|
||||
query.setFirstResult(pageable.getOffset());
|
||||
query.setMaxResults(pageable.getPageSize());
|
||||
|
||||
Long total = getCountQuery(spec).getSingleResult();
|
||||
|
||||
return new PageImpl<T>(query.getResultList(), pageable, total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link TypedQuery} from the given {@link Specification}.
|
||||
*
|
||||
* @param spec can be {@literal null}
|
||||
* @param pageable can be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
private TypedQuery<T> getQuery(Specification<T> spec, Pageable pageable) {
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<T> query = builder.createQuery(getDomainClass());
|
||||
|
||||
Root<T> root = applySpecificationToCriteria(spec, query);
|
||||
query.select(root);
|
||||
|
||||
if (pageable != null) {
|
||||
query.orderBy(toOrders(pageable.getSort(), root, builder));
|
||||
}
|
||||
|
||||
return em.createQuery(query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link TypedQuery} for the given {@link Specification} and
|
||||
* {@link Sort}.
|
||||
*
|
||||
* @param spec
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
private TypedQuery<T> getQuery(Specification<T> spec, Sort sort) {
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<T> query = builder.createQuery(getDomainClass());
|
||||
|
||||
Root<T> root = applySpecificationToCriteria(spec, query);
|
||||
query.select(root);
|
||||
|
||||
if (sort != null) {
|
||||
query.orderBy(toOrders(sort, root, builder));
|
||||
}
|
||||
|
||||
return em.createQuery(query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new count query for the given {@link Specification}.
|
||||
*
|
||||
* @param spec can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private TypedQuery<Long> getCountQuery(Specification<T> spec) {
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> query = builder.createQuery(Long.class);
|
||||
|
||||
Root<T> root = applySpecificationToCriteria(spec, query);
|
||||
query.select(builder.count(root)).distinct(true);
|
||||
|
||||
return em.createQuery(query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies the given {@link Specification} to the given
|
||||
* {@link CriteriaQuery}.
|
||||
*
|
||||
* @param spec can be {@literal null}
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
private <S> Root<T> applySpecificationToCriteria(Specification<T> spec,
|
||||
CriteriaQuery<S> query) {
|
||||
|
||||
Assert.notNull(query);
|
||||
Root<T> root = query.from(getDomainClass());
|
||||
|
||||
if (spec == null) {
|
||||
return root;
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
Predicate predicate = spec.toPredicate(root, query, builder);
|
||||
|
||||
if (predicate != null) {
|
||||
query.where(predicate);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepository<T, ID>,
|
||||
JpaSpecificationExecutor<T> {
|
||||
|
||||
private final JpaEntityInformation<T, ?> entityInformation;
|
||||
private final EntityManager em;
|
||||
private final PersistenceProvider provider;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleJpaRepository} to manage objects of the given {@link JpaEntityInformation}.
|
||||
*
|
||||
* @param entityInformation
|
||||
* @param entityManager
|
||||
*/
|
||||
public SimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
|
||||
|
||||
Assert.notNull(entityInformation);
|
||||
Assert.notNull(entityManager);
|
||||
this.entityInformation = entityInformation;
|
||||
this.em = entityManager;
|
||||
this.provider = PersistenceProvider.fromEntityManager(entityManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleJpaRepository} to manage objects of the given domain type.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param em
|
||||
*/
|
||||
public SimpleJpaRepository(Class<T> domainClass, EntityManager em) {
|
||||
|
||||
this(JpaEntityInformationSupport.getMetadata(domainClass, em), em);
|
||||
}
|
||||
|
||||
private Class<T> getDomainClass() {
|
||||
|
||||
return entityInformation.getJavaType();
|
||||
}
|
||||
|
||||
private String getDeleteAllQueryString() {
|
||||
|
||||
return getQueryString(DELETE_ALL_QUERY_STRING, entityInformation.getEntityName());
|
||||
}
|
||||
|
||||
private String getCountQueryString() {
|
||||
|
||||
String countQuery = String.format(COUNT_QUERY_STRING, provider.getCountQueryPlaceholder(), "%s");
|
||||
|
||||
return getQueryString(countQuery, entityInformation.getEntityName());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaRepository#delete(java.io.
|
||||
* Serializable)
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(ID id) {
|
||||
|
||||
delete(findOne(id));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#delete(java.lang.Object)
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(T entity) {
|
||||
|
||||
em.remove(em.contains(entity) ? entity : em.merge(entity));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#delete(java.lang.Iterable)
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(Iterable<? extends T> entities) {
|
||||
|
||||
if (entities == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (T entity : entities) {
|
||||
delete(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaRepository#deleteInBatch(java
|
||||
* .lang.Iterable)
|
||||
*/
|
||||
@Transactional
|
||||
public void deleteInBatch(Iterable<T> entities) {
|
||||
|
||||
if (null == entities || !entities.iterator().hasNext()) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyAndBind(getQueryString(DELETE_ALL_QUERY_STRING, entityInformation.getEntityName()), entities, em)
|
||||
.executeUpdate();
|
||||
em.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#deleteAll()
|
||||
*/
|
||||
@Transactional
|
||||
public void deleteAll() {
|
||||
|
||||
em.createQuery(getDeleteAllQueryString()).executeUpdate();
|
||||
em.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#readById(java.io.Serializable
|
||||
* )
|
||||
*/
|
||||
public T findOne(ID id) {
|
||||
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
return em.find(getDomainClass(), id);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#exists(java.io.Serializable
|
||||
* )
|
||||
*/
|
||||
public boolean exists(ID id) {
|
||||
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
return null != findOne(id);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#readAll()
|
||||
*/
|
||||
public List<T> findAll() {
|
||||
|
||||
return getQuery(null, (Sort) null).getResultList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#readAll(org.springframework
|
||||
* .data.domain.Sort)
|
||||
*/
|
||||
public List<T> findAll(Sort sort) {
|
||||
|
||||
return getQuery(null, sort).getResultList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#readAll(org.
|
||||
* springframework.data.domain.Pageable)
|
||||
*/
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
|
||||
if (null == pageable) {
|
||||
return new PageImpl<T>(findAll());
|
||||
}
|
||||
|
||||
return findAll(null, pageable);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.JpaRepository#findOneBy(org.
|
||||
* springframework.data.jpa.domain.Specification)
|
||||
*/
|
||||
public T findOne(Specification<T> spec) {
|
||||
|
||||
try {
|
||||
return getQuery(spec, (Sort) null).getSingleResult();
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.JpaRepository#readAll(org.
|
||||
* springframework.data.jpa.domain.Specification)
|
||||
*/
|
||||
public List<T> findAll(Specification<T> spec) {
|
||||
|
||||
return getQuery(spec, (Sort) null).getResultList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.JpaRepository#readAll(org.
|
||||
* springframework.data.jpa.domain.Specification,
|
||||
* org.springframework.data.domain.Pageable)
|
||||
*/
|
||||
public Page<T> findAll(Specification<T> spec, Pageable pageable) {
|
||||
|
||||
TypedQuery<T> query = getQuery(spec, pageable);
|
||||
|
||||
return pageable == null ? new PageImpl<T>(query.getResultList()) : readPage(query, pageable, spec);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaSpecificationExecutor#findAll
|
||||
* (org.springframework.data.jpa.domain.Specification,
|
||||
* org.springframework.data.domain.Sort)
|
||||
*/
|
||||
public List<T> findAll(Specification<T> spec, Sort sort) {
|
||||
|
||||
return getQuery(spec, sort).getResultList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.repository.Repository#count()
|
||||
*/
|
||||
public long count() {
|
||||
|
||||
return em.createQuery(getCountQueryString(), Long.class).getSingleResult();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaSpecificationExecutor#count
|
||||
* (org.springframework.data.jpa.domain.Specification)
|
||||
*/
|
||||
public long count(Specification<T> spec) {
|
||||
|
||||
return getCountQuery(spec).getSingleResult();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#save(java.lang.Object)
|
||||
*/
|
||||
@Transactional
|
||||
public T save(T entity) {
|
||||
|
||||
if (entityInformation.isNew(entity)) {
|
||||
em.persist(entity);
|
||||
return entity;
|
||||
} else {
|
||||
return em.merge(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.JpaRepository#saveAndFlush(java
|
||||
* .lang.Object)
|
||||
*/
|
||||
@Transactional
|
||||
public T saveAndFlush(T entity) {
|
||||
|
||||
T result = save(entity);
|
||||
flush();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.Repository#save(java.lang.Iterable)
|
||||
*/
|
||||
@Transactional
|
||||
public List<T> save(Iterable<? extends T> entities) {
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
|
||||
if (entities == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (T entity : entities) {
|
||||
result.add(save(entity));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.JpaRepository#flush()
|
||||
*/
|
||||
@Transactional
|
||||
public void flush() {
|
||||
|
||||
em.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the given {@link TypedQuery} into a {@link Page} applying the given {@link Pageable} and
|
||||
* {@link Specification}.
|
||||
*
|
||||
* @param query
|
||||
* @param spec
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
private Page<T> readPage(TypedQuery<T> query, Pageable pageable, Specification<T> spec) {
|
||||
|
||||
query.setFirstResult(pageable.getOffset());
|
||||
query.setMaxResults(pageable.getPageSize());
|
||||
|
||||
Long total = getCountQuery(spec).getSingleResult();
|
||||
|
||||
return new PageImpl<T>(query.getResultList(), pageable, total);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TypedQuery} from the given {@link Specification}.
|
||||
*
|
||||
* @param spec can be {@literal null}
|
||||
* @param pageable can be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
private TypedQuery<T> getQuery(Specification<T> spec, Pageable pageable) {
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<T> query = builder.createQuery(getDomainClass());
|
||||
|
||||
Root<T> root = applySpecificationToCriteria(spec, query);
|
||||
query.select(root);
|
||||
|
||||
if (pageable != null) {
|
||||
query.orderBy(toOrders(pageable.getSort(), root, builder));
|
||||
}
|
||||
|
||||
return em.createQuery(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link TypedQuery} for the given {@link Specification} and {@link Sort}.
|
||||
*
|
||||
* @param spec
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
private TypedQuery<T> getQuery(Specification<T> spec, Sort sort) {
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<T> query = builder.createQuery(getDomainClass());
|
||||
|
||||
Root<T> root = applySpecificationToCriteria(spec, query);
|
||||
query.select(root);
|
||||
|
||||
if (sort != null) {
|
||||
query.orderBy(toOrders(sort, root, builder));
|
||||
}
|
||||
|
||||
return em.createQuery(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new count query for the given {@link Specification}.
|
||||
*
|
||||
* @param spec can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private TypedQuery<Long> getCountQuery(Specification<T> spec) {
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> query = builder.createQuery(Long.class);
|
||||
|
||||
Root<T> root = applySpecificationToCriteria(spec, query);
|
||||
query.select(builder.count(root)).distinct(true);
|
||||
|
||||
return em.createQuery(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given {@link Specification} to the given {@link CriteriaQuery}.
|
||||
*
|
||||
* @param spec can be {@literal null}
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
private <S> Root<T> applySpecificationToCriteria(Specification<T> spec, CriteriaQuery<S> query) {
|
||||
|
||||
Assert.notNull(query);
|
||||
Root<T> root = query.from(getDomainClass());
|
||||
|
||||
if (spec == null) {
|
||||
return root;
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
Predicate predicate = spec.toPredicate(root, query, builder);
|
||||
|
||||
if (predicate != null) {
|
||||
query.where(predicate);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.utils;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
|
||||
/**
|
||||
* Utility class to work with classes.
|
||||
*
|
||||
@@ -25,35 +24,33 @@ import javax.persistence.EntityManager;
|
||||
*/
|
||||
public abstract class JpaClassUtils {
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private JpaClassUtils() {
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private JpaClassUtils() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link EntityManager} is of the given type.
|
||||
*
|
||||
* @param em
|
||||
* @param type the fully qualified expected {@link EntityManager} type.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean isEntityManagerOfType(EntityManager em, String type) {
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link EntityManager} is of the given type.
|
||||
*
|
||||
* @param em
|
||||
* @param type the fully qualified expected {@link EntityManager} type.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean isEntityManagerOfType(EntityManager em, String type) {
|
||||
try {
|
||||
|
||||
try {
|
||||
Class<? extends EntityManager> emType = (Class<? extends EntityManager>) Class.forName(type);
|
||||
|
||||
Class<? extends EntityManager> emType =
|
||||
(Class<? extends EntityManager>) Class.forName(type);
|
||||
emType.cast(em);
|
||||
|
||||
emType.cast(em);
|
||||
return true;
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,58 +24,50 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
|
||||
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
|
||||
|
||||
|
||||
/**
|
||||
* Extends {@link DefaultPersistenceUnitManager} to merge configurations of one
|
||||
* persistence unit residing in multiple {@code persistence.xml} files into one.
|
||||
* This is necessary to allow the declaration of entities in seperate modules.
|
||||
* Extends {@link DefaultPersistenceUnitManager} to merge configurations of one persistence unit residing in multiple
|
||||
* {@code persistence.xml} files into one. This is necessary to allow the declaration of entities in seperate modules.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @see http://jira.springframework.org/browse/SPR-2598
|
||||
*/
|
||||
public class MergingPersistenceUnitManager extends
|
||||
DefaultPersistenceUnitManager {
|
||||
public class MergingPersistenceUnitManager extends DefaultPersistenceUnitManager {
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(MergingPersistenceUnitManager.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(MergingPersistenceUnitManager.class);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager
|
||||
* #
|
||||
* postProcessPersistenceUnitInfo(org.springframework.orm.jpa.persistenceunit
|
||||
* .MutablePersistenceUnitInfo)
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager
|
||||
* #
|
||||
* postProcessPersistenceUnitInfo(org.springframework.orm.jpa.persistenceunit
|
||||
* .MutablePersistenceUnitInfo)
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
|
||||
// Invoke normal post processing
|
||||
super.postProcessPersistenceUnitInfo(pui);
|
||||
|
||||
// Invoke normal post processing
|
||||
super.postProcessPersistenceUnitInfo(pui);
|
||||
PersistenceUnitInfo oldPui = getPersistenceUnitInfo(pui.getPersistenceUnitName());
|
||||
|
||||
PersistenceUnitInfo oldPui =
|
||||
getPersistenceUnitInfo(pui.getPersistenceUnitName());
|
||||
if (oldPui != null) {
|
||||
postProcessPersistenceUnitInfo(pui, oldPui);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldPui != null) {
|
||||
postProcessPersistenceUnitInfo(pui, oldPui);
|
||||
}
|
||||
}
|
||||
void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui, PersistenceUnitInfo oldPui) {
|
||||
|
||||
for (URL url : oldPui.getJarFileUrls()) {
|
||||
|
||||
void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui,
|
||||
PersistenceUnitInfo oldPui) {
|
||||
// Add jar file url to PUI
|
||||
if (!pui.getJarFileUrls().contains(url)) {
|
||||
log.debug("Adding {} to persistence units", url);
|
||||
pui.addJarFileUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
for (URL url : oldPui.getJarFileUrls()) {
|
||||
|
||||
// Add jar file url to PUI
|
||||
if (!pui.getJarFileUrls().contains(url)) {
|
||||
log.debug("Adding {} to persistence units", url);
|
||||
pui.addJarFileUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
pui.addJarFileUrl(oldPui.getPersistenceUnitRootUrl());
|
||||
}
|
||||
pui.addJarFileUrl(oldPui.getPersistenceUnitRootUrl());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,11 @@ import javax.persistence.Entity;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class Account extends AbstractPersistable<Long> {
|
||||
|
||||
private static final long serialVersionUID = -5719129808165758887L;
|
||||
private static final long serialVersionUID = -5719129808165758887L;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import javax.persistence.Entity;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractAuditable;
|
||||
|
||||
|
||||
/**
|
||||
* Sample auditable role entity.
|
||||
*
|
||||
@@ -28,19 +27,17 @@ import org.springframework.data.jpa.domain.AbstractAuditable;
|
||||
@Entity
|
||||
public class AuditableRole extends AbstractAuditable<AuditableUser, Long> {
|
||||
|
||||
private static final long serialVersionUID = 5997359055260303863L;
|
||||
private static final long serialVersionUID = 5997359055260303863L;
|
||||
|
||||
private String name;
|
||||
private String name;
|
||||
|
||||
public void setName(String name) {
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
public String getName() {
|
||||
|
||||
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,9 @@ import javax.persistence.NamedQuery;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractAuditable;
|
||||
|
||||
|
||||
/**
|
||||
* Sample auditable user to demonstrate working with
|
||||
* {@code AbstractAuditableEntity}. No declaration of an ID is necessary.
|
||||
* Furthermore no auditing information has to be declared explicitly.
|
||||
* Sample auditable user to demonstrate working with {@code AbstractAuditableEntity}. No declaration of an ID is
|
||||
* necessary. Furthermore no auditing information has to be declared explicitly.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -37,56 +35,50 @@ import org.springframework.data.jpa.domain.AbstractAuditable;
|
||||
@NamedQuery(name = "AuditableUser.findByFirstname", query = "SELECT u FROM AuditableUser u WHERE u.firstname = ?1")
|
||||
public class AuditableUser extends AbstractAuditable<AuditableUser, Long> {
|
||||
|
||||
private static final long serialVersionUID = 7409344446795693011L;
|
||||
private static final long serialVersionUID = 7409344446795693011L;
|
||||
|
||||
private String firstname;
|
||||
private String firstname;
|
||||
|
||||
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
|
||||
private Set<AuditableRole> roles = new HashSet<AuditableRole>();
|
||||
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
|
||||
private Set<AuditableRole> roles = new HashSet<AuditableRole>();
|
||||
|
||||
public AuditableUser() {
|
||||
|
||||
public AuditableUser() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
this(null);
|
||||
}
|
||||
public AuditableUser(Long id) {
|
||||
|
||||
this.setId(id);
|
||||
}
|
||||
|
||||
public AuditableUser(Long id) {
|
||||
/**
|
||||
* Returns the firstname.
|
||||
*
|
||||
* @return the firstname
|
||||
*/
|
||||
public String getFirstname() {
|
||||
|
||||
this.setId(id);
|
||||
}
|
||||
return firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the firstname.
|
||||
*
|
||||
* @param firstname the firstname to set
|
||||
*/
|
||||
public void setFirstname(final String firstname) {
|
||||
|
||||
/**
|
||||
* Returns the firstname.
|
||||
*
|
||||
* @return the firstname
|
||||
*/
|
||||
public String getFirstname() {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
return firstname;
|
||||
}
|
||||
public void addRole(AuditableRole role) {
|
||||
|
||||
this.roles.add(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the firstname.
|
||||
*
|
||||
* @param firstname the firstname to set
|
||||
*/
|
||||
public void setFirstname(final String firstname) {
|
||||
public Set<AuditableRole> getRoles() {
|
||||
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
|
||||
public void addRole(AuditableRole role) {
|
||||
|
||||
this.roles.add(role);
|
||||
}
|
||||
|
||||
|
||||
public Set<AuditableRole> getRoles() {
|
||||
|
||||
return roles;
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,40 +19,35 @@ import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.data.jpa.repository.sample.AuditableUserRepository;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Stub implementation for {@link AuditorAware}. Returns {@literal null} for the
|
||||
* current auditor.
|
||||
* Stub implementation for {@link AuditorAware}. Returns {@literal null} for the current auditor.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AuditorAwareStub implements AuditorAware<AuditableUser> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final AuditableUserRepository repository;
|
||||
private AuditableUser auditor;
|
||||
@SuppressWarnings("unused")
|
||||
private final AuditableUserRepository repository;
|
||||
private AuditableUser auditor;
|
||||
|
||||
public AuditorAwareStub(AuditableUserRepository repository) {
|
||||
|
||||
public AuditorAwareStub(AuditableUserRepository repository) {
|
||||
Assert.notNull(repository);
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
Assert.notNull(repository);
|
||||
this.repository = repository;
|
||||
}
|
||||
public void setAuditor(AuditableUser auditor) {
|
||||
|
||||
this.auditor = auditor;
|
||||
}
|
||||
|
||||
public void setAuditor(AuditableUser auditor) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.AuditorAware#getCurrentAuditor()
|
||||
*/
|
||||
public AuditableUser getCurrentAuditor() {
|
||||
|
||||
this.auditor = auditor;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.AuditorAware#getCurrentAuditor()
|
||||
*/
|
||||
public AuditableUser getCurrentAuditor() {
|
||||
|
||||
return auditor;
|
||||
}
|
||||
return auditor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sample domain class representing roles. Mapped with XML.
|
||||
*
|
||||
@@ -24,62 +22,57 @@ package org.springframework.data.jpa.domain.sample;
|
||||
*/
|
||||
public class Role {
|
||||
|
||||
private static final long serialVersionUID = -8832631113344035104L;
|
||||
private static final String PREFIX = "ROLE_";
|
||||
private static final long serialVersionUID = -8832631113344035104L;
|
||||
private static final String PREFIX = "ROLE_";
|
||||
|
||||
private Integer id;
|
||||
private String name;
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code Role}.
|
||||
*/
|
||||
public Role() {
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code Role}.
|
||||
*/
|
||||
public Role() {
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Creates a new preconfigured {@code Role}.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public Role(final String name) {
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new preconfigured {@code Role}.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public Role(final String name) {
|
||||
/**
|
||||
* Returns the id.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Integer getId() {
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
/**
|
||||
* Returns the id.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Integer getId() {
|
||||
return PREFIX + name;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
/**
|
||||
* Returns whether the role is to be considered new.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isNew() {
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return PREFIX + name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the role is to be considered new.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isNew() {
|
||||
|
||||
return id == null;
|
||||
}
|
||||
return id == null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,48 +18,43 @@ package org.springframework.data.jpa.domain.sample;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
public class SampleEntity {
|
||||
|
||||
@EmbeddedId
|
||||
protected SampleEntityPK id;
|
||||
@EmbeddedId
|
||||
protected SampleEntityPK id;
|
||||
|
||||
protected SampleEntity() {
|
||||
|
||||
protected SampleEntity() {
|
||||
}
|
||||
|
||||
}
|
||||
public SampleEntity(String first, String second) {
|
||||
|
||||
this.id = new SampleEntityPK(first, second);
|
||||
}
|
||||
|
||||
public SampleEntity(String first, String second) {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
this.id = new SampleEntityPK(first, second);
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
SampleEntity that = (SampleEntity) obj;
|
||||
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
return this.id.equals(that.id);
|
||||
}
|
||||
|
||||
if (!getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
SampleEntity that = (SampleEntity) obj;
|
||||
|
||||
return this.id.equals(that.id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
return id.hashCode();
|
||||
}
|
||||
return id.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,67 +22,62 @@ import javax.persistence.Embeddable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
@Embeddable
|
||||
public class SampleEntityPK implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 231060947L;
|
||||
private static final long serialVersionUID = 231060947L;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String first;
|
||||
@Column(nullable = false)
|
||||
private String second;
|
||||
@Column(nullable = false)
|
||||
private String first;
|
||||
@Column(nullable = false)
|
||||
private String second;
|
||||
|
||||
public SampleEntityPK() {
|
||||
|
||||
public SampleEntityPK() {
|
||||
this.first = null;
|
||||
this.second = null;
|
||||
}
|
||||
|
||||
this.first = null;
|
||||
this.second = null;
|
||||
}
|
||||
public SampleEntityPK(String first, String second) {
|
||||
|
||||
Assert.notNull(first);
|
||||
Assert.notNull(second);
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public SampleEntityPK(String first, String second) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
Assert.notNull(first);
|
||||
Assert.notNull(second);
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
SampleEntityPK that = (SampleEntityPK) obj;
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
return this.first.equals(that.first) && this.second.equals(that.second);
|
||||
}
|
||||
|
||||
if (!this.getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
SampleEntityPK that = (SampleEntityPK) obj;
|
||||
|
||||
return this.first.equals(that.first) && this.second.equals(that.second);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
result += 31 * first.hashCode();
|
||||
result += 31 * second.hashCode();
|
||||
return result;
|
||||
}
|
||||
int result = 17;
|
||||
result += 31 * first.hashCode();
|
||||
result += 31 * second.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.springframework.data.jpa.domain.sample;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
|
||||
@@ -28,11 +28,9 @@ import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQuery;
|
||||
|
||||
|
||||
/**
|
||||
* Domain class representing a person emphasizing the use of
|
||||
* {@code AbstractEntity}. No declaration of an id is required. The id is typed
|
||||
* by the parameterizable superclass.
|
||||
* Domain class representing a person emphasizing the use of {@code AbstractEntity}. No declaration of an id is
|
||||
* required. The id is typed by the parameterizable superclass.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -40,260 +38,236 @@ import javax.persistence.NamedQuery;
|
||||
@NamedQuery(name = "User.findByEmailAddress", query = "SELECT u FROM User u WHERE u.emailAddress = ?1")
|
||||
public class User {
|
||||
|
||||
private static final long serialVersionUID = 8653688953355455933L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Integer id;
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String emailAddress;
|
||||
|
||||
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
|
||||
private Set<User> colleagues;
|
||||
|
||||
@ManyToMany
|
||||
private Set<Role> roles;
|
||||
|
||||
@ManyToOne
|
||||
private User manager;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new empty instance of {@code User}.
|
||||
*/
|
||||
public User() {
|
||||
|
||||
this.roles = new HashSet<Role>();
|
||||
this.colleagues = new HashSet<User>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code User} with preinitialized values for
|
||||
* firstname, lastname and email address.
|
||||
*
|
||||
* @param firstname
|
||||
* @param lastname
|
||||
* @param emailAddress
|
||||
*/
|
||||
public User(final String firstname, final String lastname,
|
||||
final String emailAddress) {
|
||||
|
||||
this();
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public Integer getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param id the id to set
|
||||
*/
|
||||
public void setId(Integer id) {
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the firstname.
|
||||
*
|
||||
* @return the firstname
|
||||
*/
|
||||
public String getFirstname() {
|
||||
|
||||
return firstname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the firstname.
|
||||
*
|
||||
* @param firstname the firstname to set
|
||||
*/
|
||||
public void setFirstname(final String firstname) {
|
||||
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the lastname.
|
||||
*
|
||||
* @return the lastname
|
||||
*/
|
||||
public String getLastname() {
|
||||
|
||||
return lastname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the lastname.
|
||||
*
|
||||
* @param lastname the lastname to set
|
||||
*/
|
||||
public void setLastname(String lastname) {
|
||||
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the email address.
|
||||
*
|
||||
* @return the emailAddress
|
||||
*/
|
||||
public String getEmailAddress() {
|
||||
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the email address.
|
||||
*
|
||||
* @param emailAddress the emailAddress to set
|
||||
*/
|
||||
public void setEmailAddress(String emailAddress) {
|
||||
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the user's roles.
|
||||
*
|
||||
* @return the role
|
||||
*/
|
||||
public Set<Role> getRole() {
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gives the user a role. Adding a role the user already owns is a no-op.
|
||||
*/
|
||||
public void addRole(Role role) {
|
||||
|
||||
roles.add(role);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Revokes a role from a user.
|
||||
*
|
||||
* @param role
|
||||
*/
|
||||
public void removeRole(Role role) {
|
||||
|
||||
roles.remove(role);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the colleagues of the user.
|
||||
*
|
||||
* @return the colleagues
|
||||
*/
|
||||
public Set<User> getColleagues() {
|
||||
|
||||
return colleagues;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new colleague to the user. Adding the user himself as colleague is
|
||||
* a no-op.
|
||||
*
|
||||
* @param collegue
|
||||
*/
|
||||
public void addColleague(User collegue) {
|
||||
|
||||
// Prevent from adding the user himself as colleague.
|
||||
if (this.equals(collegue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
colleagues.add(collegue);
|
||||
collegue.getColleagues().add(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes a colleague from the list of colleagues.
|
||||
*
|
||||
* @param colleague
|
||||
*/
|
||||
public void removeColleague(User colleague) {
|
||||
|
||||
colleagues.remove(colleague);
|
||||
colleague.getColleagues().remove(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the manager
|
||||
*/
|
||||
public User getManager() {
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param manager the manager to set
|
||||
*/
|
||||
public void setManager(User manager) {
|
||||
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (!(obj instanceof User)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
User that = (User) obj;
|
||||
|
||||
if (null == this.getId() || null == that.getId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getId().equals(that.getId());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return "User: " + getId() + ", " + getFirstname() + " " + getLastname()
|
||||
+ ", " + getEmailAddress();
|
||||
}
|
||||
private static final long serialVersionUID = 8653688953355455933L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Integer id;
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String emailAddress;
|
||||
|
||||
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
|
||||
private Set<User> colleagues;
|
||||
|
||||
@ManyToMany
|
||||
private Set<Role> roles;
|
||||
|
||||
@ManyToOne
|
||||
private User manager;
|
||||
|
||||
/**
|
||||
* Creates a new empty instance of {@code User}.
|
||||
*/
|
||||
public User() {
|
||||
|
||||
this.roles = new HashSet<Role>();
|
||||
this.colleagues = new HashSet<User>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code User} with preinitialized values for firstname, lastname and email address.
|
||||
*
|
||||
* @param firstname
|
||||
* @param lastname
|
||||
* @param emailAddress
|
||||
*/
|
||||
public User(final String firstname, final String lastname, final String emailAddress) {
|
||||
|
||||
this();
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public Integer getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id the id to set
|
||||
*/
|
||||
public void setId(Integer id) {
|
||||
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the firstname.
|
||||
*
|
||||
* @return the firstname
|
||||
*/
|
||||
public String getFirstname() {
|
||||
|
||||
return firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the firstname.
|
||||
*
|
||||
* @param firstname the firstname to set
|
||||
*/
|
||||
public void setFirstname(final String firstname) {
|
||||
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lastname.
|
||||
*
|
||||
* @return the lastname
|
||||
*/
|
||||
public String getLastname() {
|
||||
|
||||
return lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lastname.
|
||||
*
|
||||
* @param lastname the lastname to set
|
||||
*/
|
||||
public void setLastname(String lastname) {
|
||||
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the email address.
|
||||
*
|
||||
* @return the emailAddress
|
||||
*/
|
||||
public String getEmailAddress() {
|
||||
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the email address.
|
||||
*
|
||||
* @param emailAddress the emailAddress to set
|
||||
*/
|
||||
public void setEmailAddress(String emailAddress) {
|
||||
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's roles.
|
||||
*
|
||||
* @return the role
|
||||
*/
|
||||
public Set<Role> getRole() {
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the user a role. Adding a role the user already owns is a no-op.
|
||||
*/
|
||||
public void addRole(Role role) {
|
||||
|
||||
roles.add(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes a role from a user.
|
||||
*
|
||||
* @param role
|
||||
*/
|
||||
public void removeRole(Role role) {
|
||||
|
||||
roles.remove(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the colleagues of the user.
|
||||
*
|
||||
* @return the colleagues
|
||||
*/
|
||||
public Set<User> getColleagues() {
|
||||
|
||||
return colleagues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new colleague to the user. Adding the user himself as colleague is a no-op.
|
||||
*
|
||||
* @param collegue
|
||||
*/
|
||||
public void addColleague(User collegue) {
|
||||
|
||||
// Prevent from adding the user himself as colleague.
|
||||
if (this.equals(collegue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
colleagues.add(collegue);
|
||||
collegue.getColleagues().add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a colleague from the list of colleagues.
|
||||
*
|
||||
* @param colleague
|
||||
*/
|
||||
public void removeColleague(User colleague) {
|
||||
|
||||
colleagues.remove(colleague);
|
||||
colleague.getColleagues().remove(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the manager
|
||||
*/
|
||||
public User getManager() {
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param manager the manager to set
|
||||
*/
|
||||
public void setManager(User manager) {
|
||||
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (!(obj instanceof User)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
User that = (User) obj;
|
||||
|
||||
if (null == this.getId() || null == that.getId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getId().equals(that.getId());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return "User: " + getId() + ", " + getFirstname() + " " + getLastname() + ", " + getEmailAddress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import javax.persistence.criteria.Root;
|
||||
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
|
||||
/**
|
||||
* Collection of {@link Specification}s for a {@link User}.
|
||||
*
|
||||
@@ -30,61 +29,53 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
*/
|
||||
public class UserSpecifications {
|
||||
|
||||
/**
|
||||
* A {@link Specification} to match on a {@link User}'s firstname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public static Specification<User> userHasFirstname(final String firstname) {
|
||||
/**
|
||||
* A {@link Specification} to match on a {@link User}'s firstname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public static Specification<User> userHasFirstname(final String firstname) {
|
||||
|
||||
return simplePropertySpec("firstname", firstname);
|
||||
}
|
||||
return simplePropertySpec("firstname", firstname);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Specification} to match on a {@link User}'s lastname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public static Specification<User> userHasLastname(final String lastname) {
|
||||
|
||||
/**
|
||||
* A {@link Specification} to match on a {@link User}'s lastname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public static Specification<User> userHasLastname(final String lastname) {
|
||||
return simplePropertySpec("lastname", lastname);
|
||||
}
|
||||
|
||||
return simplePropertySpec("lastname", lastname);
|
||||
}
|
||||
/**
|
||||
* A {@link Specification} to do a like-match on a {@link User}'s firstname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public static Specification<User> userHasFirstnameLike(final String expression) {
|
||||
|
||||
return new Specification<User>() {
|
||||
|
||||
/**
|
||||
* A {@link Specification} to do a like-match on a {@link User}'s firstname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
public static Specification<User> userHasFirstnameLike(
|
||||
final String expression) {
|
||||
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
|
||||
|
||||
return new Specification<User>() {
|
||||
return cb.like(root.get("firstname").as(String.class), String.format("%%%s%%", expression));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Predicate toPredicate(Root<User> root,
|
||||
CriteriaQuery<?> query, CriteriaBuilder cb) {
|
||||
private static <T> Specification<T> simplePropertySpec(final String property, final Object value) {
|
||||
|
||||
return cb.like(root.get("firstname").as(String.class),
|
||||
String.format("%%%s%%", expression));
|
||||
}
|
||||
};
|
||||
}
|
||||
return new Specification<T>() {
|
||||
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
|
||||
private static <T> Specification<T> simplePropertySpec(
|
||||
final String property, final Object value) {
|
||||
|
||||
return new Specification<T>() {
|
||||
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
|
||||
CriteriaBuilder builder) {
|
||||
|
||||
return builder.equal(root.get(property), value);
|
||||
}
|
||||
};
|
||||
}
|
||||
return builder.equal(root.get(property), value);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link AuditingBeanFactoryPostProcessor}.
|
||||
*
|
||||
@@ -34,38 +33,30 @@ import org.springframework.core.io.ClassPathResource;
|
||||
*/
|
||||
public class AuditingBeanFactoryPostProcessorUnitTests {
|
||||
|
||||
ConfigurableListableBeanFactory beanFactory;
|
||||
AuditingBeanFactoryPostProcessor processor;
|
||||
ConfigurableListableBeanFactory beanFactory;
|
||||
AuditingBeanFactoryPostProcessor processor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
beanFactory = new XmlBeanFactory(new ClassPathResource("auditing/" + getConfigFile()));
|
||||
|
||||
beanFactory =
|
||||
new XmlBeanFactory(new ClassPathResource("auditing/"
|
||||
+ getConfigFile()));
|
||||
processor = new AuditingBeanFactoryPostProcessor();
|
||||
}
|
||||
|
||||
processor = new AuditingBeanFactoryPostProcessor();
|
||||
}
|
||||
protected String getConfigFile() {
|
||||
|
||||
return "auditing-bfpp-context.xml";
|
||||
}
|
||||
|
||||
protected String getConfigFile() {
|
||||
@Test
|
||||
public void testname() throws Exception {
|
||||
|
||||
return "auditing-bfpp-context.xml";
|
||||
}
|
||||
processor.postProcessBeanFactory(beanFactory);
|
||||
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition("entityManagerFactory");
|
||||
|
||||
@Test
|
||||
public void testname() throws Exception {
|
||||
|
||||
processor.postProcessBeanFactory(beanFactory);
|
||||
|
||||
BeanDefinition definition =
|
||||
beanFactory.getBeanDefinition("entityManagerFactory");
|
||||
|
||||
assertTrue(Arrays
|
||||
.asList(definition.getDependsOn())
|
||||
.contains(
|
||||
AuditingBeanFactoryPostProcessor.BEAN_CONFIGURER_ASPECT_BEAN_NAME));
|
||||
}
|
||||
assertTrue(Arrays.asList(definition.getDependsOn()).contains(
|
||||
AuditingBeanFactoryPostProcessor.BEAN_CONFIGURER_ASPECT_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for {@link AuditingEntityListener}.
|
||||
*
|
||||
@@ -44,61 +43,55 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@DirtiesContext
|
||||
public class AuditingEntityListenerTests {
|
||||
|
||||
@Autowired
|
||||
AuditableUserRepository repository;
|
||||
@Autowired
|
||||
AuditableUserRepository repository;
|
||||
|
||||
@Autowired
|
||||
AuditorAwareStub auditorAware;
|
||||
@Autowired
|
||||
AuditorAwareStub auditorAware;
|
||||
|
||||
AuditableUser user;
|
||||
AuditableUser user;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
user = new AuditableUser();
|
||||
auditorAware.setAuditor(user);
|
||||
|
||||
user = new AuditableUser();
|
||||
auditorAware.setAuditor(user);
|
||||
repository.save(user);
|
||||
}
|
||||
|
||||
repository.save(user);
|
||||
}
|
||||
@Test
|
||||
public void auditsRootEntityCorrectly() throws Exception {
|
||||
|
||||
assertDatesSet(user);
|
||||
assertUserIsAuditor(user, user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void auditsRootEntityCorrectly() throws Exception {
|
||||
@Test
|
||||
public void auditsTransitiveEntitiesCorrectly() throws Exception {
|
||||
|
||||
assertDatesSet(user);
|
||||
assertUserIsAuditor(user, user);
|
||||
}
|
||||
AuditableRole role = new AuditableRole();
|
||||
role.setName("ADMIN");
|
||||
|
||||
user.addRole(role);
|
||||
repository.save(user);
|
||||
role = user.getRoles().iterator().next();
|
||||
|
||||
@Test
|
||||
public void auditsTransitiveEntitiesCorrectly() throws Exception {
|
||||
assertDatesSet(user);
|
||||
assertDatesSet(role);
|
||||
assertUserIsAuditor(user, user);
|
||||
assertUserIsAuditor(user, role);
|
||||
}
|
||||
|
||||
AuditableRole role = new AuditableRole();
|
||||
role.setName("ADMIN");
|
||||
private static void assertDatesSet(Auditable<?, ?> auditable) {
|
||||
|
||||
user.addRole(role);
|
||||
repository.save(user);
|
||||
role = user.getRoles().iterator().next();
|
||||
assertThat(auditable.getCreatedDate(), is(notNullValue()));
|
||||
assertThat(auditable.getLastModifiedDate(), is(notNullValue()));
|
||||
}
|
||||
|
||||
assertDatesSet(user);
|
||||
assertDatesSet(role);
|
||||
assertUserIsAuditor(user, user);
|
||||
assertUserIsAuditor(user, role);
|
||||
}
|
||||
private static void assertUserIsAuditor(AuditableUser user, Auditable<AuditableUser, ?> auditable) {
|
||||
|
||||
|
||||
private static void assertDatesSet(Auditable<?, ?> auditable) {
|
||||
|
||||
assertThat(auditable.getCreatedDate(), is(notNullValue()));
|
||||
assertThat(auditable.getLastModifiedDate(), is(notNullValue()));
|
||||
}
|
||||
|
||||
|
||||
private static void assertUserIsAuditor(AuditableUser user,
|
||||
Auditable<AuditableUser, ?> auditable) {
|
||||
|
||||
assertThat(auditable.getCreatedBy(), is(user));
|
||||
assertThat(auditable.getLastModifiedBy(), is(user));
|
||||
}
|
||||
assertThat(auditable.getCreatedBy(), is(user));
|
||||
assertThat(auditable.getLastModifiedBy(), is(user));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.junit.Test;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.data.jpa.domain.sample.AuditableUser;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@code AuditingEntityListener}.
|
||||
*
|
||||
@@ -32,119 +31,109 @@ import org.springframework.data.jpa.domain.sample.AuditableUser;
|
||||
@SuppressWarnings("unchecked")
|
||||
public class AuditingEntityListenerUnitTests {
|
||||
|
||||
AuditingEntityListener<AuditableUser> listener;
|
||||
AuditorAware<AuditableUser> auditorAware;
|
||||
AuditingEntityListener<AuditableUser> listener;
|
||||
AuditorAware<AuditableUser> auditorAware;
|
||||
|
||||
AuditableUser user;
|
||||
AuditableUser user;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
listener = new AuditingEntityListener<AuditableUser>();
|
||||
// Explicitly null the AuditorAware as it might have been DI'ed if test
|
||||
// is run in a test suite with integration tests
|
||||
// listener.setAuditorAware(null);
|
||||
|
||||
listener = new AuditingEntityListener<AuditableUser>();
|
||||
// Explicitly null the AuditorAware as it might have been DI'ed if test
|
||||
// is run in a test suite with integration tests
|
||||
// listener.setAuditorAware(null);
|
||||
user = new AuditableUser();
|
||||
|
||||
user = new AuditableUser();
|
||||
auditorAware = mock(AuditorAware.class);
|
||||
when(auditorAware.getCurrentAuditor()).thenReturn(user);
|
||||
}
|
||||
|
||||
auditorAware = mock(AuditorAware.class);
|
||||
when(auditorAware.getCurrentAuditor()).thenReturn(user);
|
||||
}
|
||||
/**
|
||||
* Checks that the advice does not set auditor on the target entity if no {@code AuditorAware} was configured.
|
||||
*/
|
||||
@Test
|
||||
public void doesNotSetAuditorIfNotConfigured() {
|
||||
|
||||
listener.touchForCreate(user);
|
||||
|
||||
/**
|
||||
* Checks that the advice does not set auditor on the target entity if no
|
||||
* {@code AuditorAware} was configured.
|
||||
*/
|
||||
@Test
|
||||
public void doesNotSetAuditorIfNotConfigured() {
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
|
||||
listener.touchForCreate(user);
|
||||
assertNull(user.getCreatedBy());
|
||||
assertNull(user.getLastModifiedBy());
|
||||
}
|
||||
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
/**
|
||||
* Checks that the advice sets the auditor on the target entity if an {@code AuditorAware} was configured.
|
||||
*/
|
||||
@Test
|
||||
public void setsAuditorIfConfigured() {
|
||||
|
||||
assertNull(user.getCreatedBy());
|
||||
assertNull(user.getLastModifiedBy());
|
||||
}
|
||||
listener.setAuditorAware(auditorAware);
|
||||
|
||||
listener.touchForCreate(user);
|
||||
|
||||
/**
|
||||
* Checks that the advice sets the auditor on the target entity if an
|
||||
* {@code AuditorAware} was configured.
|
||||
*/
|
||||
@Test
|
||||
public void setsAuditorIfConfigured() {
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
|
||||
listener.setAuditorAware(auditorAware);
|
||||
assertNotNull(user.getCreatedBy());
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
|
||||
listener.touchForCreate(user);
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
/**
|
||||
* Checks that the advice does not set modification information on creation if the falg is set to {@code false}.
|
||||
*/
|
||||
@Test
|
||||
public void honoursModifiedOnCreationFlag() {
|
||||
|
||||
assertNotNull(user.getCreatedBy());
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
listener.setAuditorAware(auditorAware);
|
||||
listener.setModifyOnCreation(false);
|
||||
listener.touchForCreate(user);
|
||||
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getCreatedBy());
|
||||
|
||||
assertNull(user.getLastModifiedBy());
|
||||
assertNull(user.getLastModifiedDate());
|
||||
|
||||
/**
|
||||
* Checks that the advice does not set modification information on creation
|
||||
* if the falg is set to {@code false}.
|
||||
*/
|
||||
@Test
|
||||
public void honoursModifiedOnCreationFlag() {
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
|
||||
listener.setAuditorAware(auditorAware);
|
||||
listener.setModifyOnCreation(false);
|
||||
listener.touchForCreate(user);
|
||||
/**
|
||||
* Tests that the advice only sets modification data if a not-new entity is handled.
|
||||
*/
|
||||
@Test
|
||||
public void onlySetsModificationDataOnNotNewEntities() {
|
||||
|
||||
assertNotNull(user.getCreatedDate());
|
||||
assertNotNull(user.getCreatedBy());
|
||||
user = new AuditableUser(1L);
|
||||
|
||||
assertNull(user.getLastModifiedBy());
|
||||
assertNull(user.getLastModifiedDate());
|
||||
listener.setAuditorAware(auditorAware);
|
||||
listener.touchForUpdate(user);
|
||||
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
assertNull(user.getCreatedBy());
|
||||
assertNull(user.getCreatedDate());
|
||||
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
|
||||
/**
|
||||
* Tests that the advice only sets modification data if a not-new entity is
|
||||
* handled.
|
||||
*/
|
||||
@Test
|
||||
public void onlySetsModificationDataOnNotNewEntities() {
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
|
||||
user = new AuditableUser(1L);
|
||||
@Test
|
||||
public void doesNotSetTimeIfConfigured() throws Exception {
|
||||
|
||||
listener.setAuditorAware(auditorAware);
|
||||
listener.touchForUpdate(user);
|
||||
listener.setDateTimeForNow(false);
|
||||
listener.setAuditorAware(auditorAware);
|
||||
listener.touchForCreate(user);
|
||||
|
||||
assertNull(user.getCreatedBy());
|
||||
assertNull(user.getCreatedDate());
|
||||
assertNotNull(user.getCreatedBy());
|
||||
assertNull(user.getCreatedDate());
|
||||
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
assertNotNull(user.getLastModifiedDate());
|
||||
|
||||
verify(auditorAware).getCurrentAuditor();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doesNotSetTimeIfConfigured() throws Exception {
|
||||
|
||||
listener.setDateTimeForNow(false);
|
||||
listener.setAuditorAware(auditorAware);
|
||||
listener.touchForCreate(user);
|
||||
|
||||
assertNotNull(user.getCreatedBy());
|
||||
assertNull(user.getCreatedDate());
|
||||
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
assertNull(user.getLastModifiedDate());
|
||||
}
|
||||
assertNotNull(user.getLastModifiedBy());
|
||||
assertNull(user.getLastModifiedDate());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,36 +22,30 @@ import org.junit.Test;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for the JPA {@code auditing} namespace element.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AuditingNamespaceUnitTests extends
|
||||
AuditingBeanFactoryPostProcessorUnitTests {
|
||||
public class AuditingNamespaceUnitTests extends AuditingBeanFactoryPostProcessorUnitTests {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.domain.support.
|
||||
* AuditingBeanFactoryPostProcessorUnitTests#getConfigFile()
|
||||
*/
|
||||
@Override
|
||||
protected String getConfigFile() {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.domain.support.
|
||||
* AuditingBeanFactoryPostProcessorUnitTests#getConfigFile()
|
||||
*/
|
||||
@Override
|
||||
protected String getConfigFile() {
|
||||
|
||||
return "auditing-namespace-context.xml";
|
||||
}
|
||||
return "auditing-namespace-context.xml";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersBeanDefinitions() throws Exception {
|
||||
|
||||
@Test
|
||||
public void registersBeanDefinitions() throws Exception {
|
||||
|
||||
BeanDefinition definition =
|
||||
beanFactory.getBeanDefinition(AuditingEntityListener.class
|
||||
.getName());
|
||||
PropertyValue propertyValue =
|
||||
definition.getPropertyValues().getPropertyValue("auditorAware");
|
||||
assertThat(propertyValue, is(notNullValue()));
|
||||
}
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(AuditingEntityListener.class.getName());
|
||||
PropertyValue propertyValue = definition.getPropertyValues().getPropertyValue("auditorAware");
|
||||
assertThat(propertyValue, is(notNullValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,13 @@ import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Testcase to run {@link UserRepository} integration tests on top of
|
||||
* EclipseLink.
|
||||
* Testcase to run {@link UserRepository} integration tests on top of EclipseLink.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@DirtiesContext
|
||||
@ContextConfiguration(value = "classpath:eclipselink.xml", inheritLocations = true)
|
||||
public class EclipseLinkNamespaceUserRepositoryTests extends
|
||||
NamespaceUserRepositoryTests {
|
||||
public class EclipseLinkNamespaceUserRepositoryTests extends NamespaceUserRepositoryTests {
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.junit.Ignore;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Ignores some test cases using IN queries as long as we wait for fix for
|
||||
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477.
|
||||
@@ -29,6 +28,5 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
@Ignore
|
||||
@DirtiesContext
|
||||
@ContextConfiguration(value = "classpath:eclipselink.xml", inheritLocations = true)
|
||||
public class EclipseLinkUserRepositoryFinderTests extends
|
||||
UserRepositoryFinderTests {
|
||||
public class EclipseLinkUserRepositoryFinderTests extends UserRepositoryFinderTests {
|
||||
}
|
||||
|
||||
@@ -26,10 +26,8 @@ import org.springframework.dao.annotation.PersistenceExceptionTranslationPostPro
|
||||
import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Use namespace context to run tests. Checks for existence of required
|
||||
* PostProcessors, too.
|
||||
* Use namespace context to run tests. Checks for existence of required PostProcessors, too.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Eberhard Wolff
|
||||
@@ -37,21 +35,19 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-application-context.xml", inheritLocations = false)
|
||||
public class NamespaceUserRepositoryTests extends UserRepositoryTests {
|
||||
|
||||
@Autowired
|
||||
ListableBeanFactory beanFactory;
|
||||
@Autowired
|
||||
ListableBeanFactory beanFactory;
|
||||
|
||||
@Test
|
||||
public void registersPostProcessors() {
|
||||
|
||||
@Test
|
||||
public void registersPostProcessors() {
|
||||
hasAtLeastOneBeanOfType(PersistenceAnnotationBeanPostProcessor.class);
|
||||
hasAtLeastOneBeanOfType(PersistenceExceptionTranslationPostProcessor.class);
|
||||
}
|
||||
|
||||
hasAtLeastOneBeanOfType(PersistenceAnnotationBeanPostProcessor.class);
|
||||
hasAtLeastOneBeanOfType(PersistenceExceptionTranslationPostProcessor.class);
|
||||
}
|
||||
private void hasAtLeastOneBeanOfType(Class<?> beanType) {
|
||||
|
||||
|
||||
private void hasAtLeastOneBeanOfType(Class<?> beanType) {
|
||||
|
||||
Map<String, ?> beans = beanFactory.getBeansOfType(beanType);
|
||||
assertFalse(beans.entrySet().isEmpty());
|
||||
}
|
||||
Map<String, ?> beans = beanFactory.getBeansOfType(beanType);
|
||||
assertFalse(beans.entrySet().isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,8 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Simple test case launching an {@code ApplicationContext} to test
|
||||
* infrastructure configuration.
|
||||
* Simple test case launching an {@code ApplicationContext} to test infrastructure configuration.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -35,18 +33,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@ContextConfiguration(locations = "classpath:infrastructure.xml")
|
||||
public class ORMInfrastructureTests {
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
/**
|
||||
* Tests, that the context got initialized and injected correctly.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void contextInitialized() throws Exception {
|
||||
|
||||
/**
|
||||
* Tests, that the context got initialized and injected correctly.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void contextInitialized() throws Exception {
|
||||
|
||||
assertNotNull(context);
|
||||
}
|
||||
assertNotNull(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,12 @@ package org.springframework.data.jpa.repository;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Testcase to run {@link UserRepository} integration tests on top of OpenJPA.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(value = "classpath:openjpa.xml", inheritLocations = true)
|
||||
public class OpenJpaNamespaceUserRepositoryTests extends
|
||||
NamespaceUserRepositoryTests {
|
||||
public class OpenJpaNamespaceUserRepositoryTests extends NamespaceUserRepositoryTests {
|
||||
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Integration tests for {@link RoleRepository}.
|
||||
*
|
||||
@@ -39,30 +38,28 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Transactional
|
||||
public class RoleRepositoryIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
RoleRepository repository;
|
||||
@Autowired
|
||||
RoleRepository repository;
|
||||
|
||||
@Test
|
||||
public void createsRole() throws Exception {
|
||||
|
||||
@Test
|
||||
public void createsRole() throws Exception {
|
||||
Role reference = new Role("ADMIN");
|
||||
Role result = repository.save(reference);
|
||||
assertThat(result, is(reference));
|
||||
}
|
||||
|
||||
Role reference = new Role("ADMIN");
|
||||
Role result = repository.save(reference);
|
||||
assertThat(result, is(reference));
|
||||
}
|
||||
@Test
|
||||
public void updatesRole() throws Exception {
|
||||
|
||||
Role reference = new Role("ADMIN");
|
||||
Role result = repository.save(reference);
|
||||
assertThat(result, is(reference));
|
||||
|
||||
@Test
|
||||
public void updatesRole() throws Exception {
|
||||
// Change role name
|
||||
ReflectionTestUtils.setField(reference, "name", "USER");
|
||||
repository.save(reference);
|
||||
|
||||
Role reference = new Role("ADMIN");
|
||||
Role result = repository.save(reference);
|
||||
assertThat(result, is(reference));
|
||||
|
||||
// Change role name
|
||||
ReflectionTestUtils.setField(reference, "name", "USER");
|
||||
repository.save(reference);
|
||||
|
||||
assertThat(repository.findOne(result.getId()), is(reference));
|
||||
}
|
||||
assertThat(repository.findOne(result.getId()), is(reference));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -50,56 +49,52 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Transactional
|
||||
public class SimpleJpaParameterBindingTests {
|
||||
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void bindArray() {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void bindArray() {
|
||||
User user = new User("Dave", "Matthews", "foo@bar.de");
|
||||
em.persist(user);
|
||||
em.flush();
|
||||
|
||||
User user = new User("Dave", "Matthews", "foo@bar.de");
|
||||
em.persist(user);
|
||||
em.flush();
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<User> criteria = builder.createQuery(User.class);
|
||||
Root<User> root = criteria.from(User.class);
|
||||
ParameterExpression<String[]> parameter = builder.parameter(String[].class);
|
||||
criteria.where(root.get("firstname").in(parameter));
|
||||
|
||||
CriteriaQuery<User> criteria = builder.createQuery(User.class);
|
||||
Root<User> root = criteria.from(User.class);
|
||||
ParameterExpression<String[]> parameter =
|
||||
builder.parameter(String[].class);
|
||||
criteria.where(root.get("firstname").in(parameter));
|
||||
TypedQuery<User> query = em.createQuery(criteria);
|
||||
query.setParameter(parameter, new String[] { "Dave", "Carter" });
|
||||
|
||||
TypedQuery<User> query = em.createQuery(criteria);
|
||||
query.setParameter(parameter, new String[] { "Dave", "Carter" });
|
||||
List<User> result = query.getResultList();
|
||||
assertThat(result.isEmpty(), is(false));
|
||||
}
|
||||
|
||||
List<User> result = query.getResultList();
|
||||
assertThat(result.isEmpty(), is(false));
|
||||
}
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void bindCollection() {
|
||||
|
||||
User user = new User("Dave", "Matthews", "foo@bar.de");
|
||||
em.persist(user);
|
||||
em.flush();
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void bindCollection() {
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
|
||||
User user = new User("Dave", "Matthews", "foo@bar.de");
|
||||
em.persist(user);
|
||||
em.flush();
|
||||
CriteriaQuery<User> criteria = builder.createQuery(User.class);
|
||||
Root<User> root = criteria.from(User.class);
|
||||
ParameterExpression<Collection> parameter = builder.parameter(Collection.class);
|
||||
criteria.where(root.get("firstname").in(parameter));
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
TypedQuery<User> query = em.createQuery(criteria);
|
||||
|
||||
CriteriaQuery<User> criteria = builder.createQuery(User.class);
|
||||
Root<User> root = criteria.from(User.class);
|
||||
ParameterExpression<Collection> parameter =
|
||||
builder.parameter(Collection.class);
|
||||
criteria.where(root.get("firstname").in(parameter));
|
||||
query.setParameter(parameter, Arrays.asList("Dave"));
|
||||
|
||||
TypedQuery<User> query = em.createQuery(criteria);
|
||||
|
||||
query.setParameter(parameter, Arrays.asList("Dave"));
|
||||
|
||||
List<User> result = query.getResultList();
|
||||
assertThat(result.isEmpty(), is(false));
|
||||
assertThat(result.get(0), is(user));
|
||||
}
|
||||
List<User> result = query.getResultList();
|
||||
assertThat(result.isEmpty(), is(false));
|
||||
assertThat(result.get(0), is(user));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,8 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for executing finders, thus testing various query lookup
|
||||
* strategies.
|
||||
* Integration test for executing finders, thus testing various query lookup strategies.
|
||||
*
|
||||
* @see QueryLookupStrategy
|
||||
* @author Oliver Gierke
|
||||
@@ -49,134 +47,108 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Transactional
|
||||
public class UserRepositoryFinderTests {
|
||||
|
||||
@Autowired
|
||||
UserRepository userRepository;
|
||||
@Autowired
|
||||
UserRepository userRepository;
|
||||
|
||||
User dave, carter, oliver;
|
||||
User dave, carter, oliver;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// This one matches both criterias
|
||||
dave = new User("Dave", "Matthews", "dave@dmband.com");
|
||||
userRepository.save(dave);
|
||||
|
||||
// This one matches both criterias
|
||||
dave = new User("Dave", "Matthews", "dave@dmband.com");
|
||||
userRepository.save(dave);
|
||||
// This one matches only the second one
|
||||
carter = new User("Carter", "Beauford", "carter@dmband.com");
|
||||
userRepository.save(carter);
|
||||
|
||||
// This one matches only the second one
|
||||
carter = new User("Carter", "Beauford", "carter@dmband.com");
|
||||
userRepository.save(carter);
|
||||
oliver = new User("Oliver August", "Matthews", "oliver@dmband.com");
|
||||
userRepository.save(oliver);
|
||||
}
|
||||
|
||||
oliver = new User("Oliver August", "Matthews", "oliver@dmband.com");
|
||||
userRepository.save(oliver);
|
||||
}
|
||||
/**
|
||||
* Tests creation of a simple query.
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleCustomCreatedFinder() {
|
||||
|
||||
User user = userRepository.findByEmailAddressAndLastname("dave@dmband.com", "Matthews");
|
||||
assertEquals(dave, user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creation of a simple query.
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleCustomCreatedFinder() {
|
||||
/**
|
||||
* Tests that the repository returns {@code null} for not found objects for finder methods that return a single domain
|
||||
* object.
|
||||
*/
|
||||
@Test
|
||||
public void returnsNullIfNothingFound() {
|
||||
|
||||
User user =
|
||||
userRepository.findByEmailAddressAndLastname("dave@dmband.com",
|
||||
"Matthews");
|
||||
assertEquals(dave, user);
|
||||
}
|
||||
User user = userRepository.findByEmailAddress("foobar");
|
||||
assertEquals(null, user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creation of a simple query consisting of {@code AND} and {@code OR} parts.
|
||||
*/
|
||||
@Test
|
||||
public void testAndOrFinder() {
|
||||
|
||||
/**
|
||||
* Tests that the repository returns {@code null} for not found objects for
|
||||
* finder methods that return a single domain object.
|
||||
*/
|
||||
@Test
|
||||
public void returnsNullIfNothingFound() {
|
||||
List<User> users = userRepository.findByEmailAddressAndLastnameOrFirstname("dave@dmband.com", "Matthews", "Carter");
|
||||
|
||||
User user = userRepository.findByEmailAddress("foobar");
|
||||
assertEquals(null, user);
|
||||
}
|
||||
assertNotNull(users);
|
||||
assertEquals(2, users.size());
|
||||
assertTrue(users.contains(dave));
|
||||
assertTrue(users.contains(carter));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executesPagingMethodToPageCorrectly() {
|
||||
|
||||
/**
|
||||
* Tests creation of a simple query consisting of {@code AND} and {@code OR}
|
||||
* parts.
|
||||
*/
|
||||
@Test
|
||||
public void testAndOrFinder() {
|
||||
Page<User> page = userRepository.findByLastname(new PageRequest(0, 1), "Matthews");
|
||||
assertThat(page.getNumberOfElements(), is(1));
|
||||
assertThat(page.getTotalElements(), is(2L));
|
||||
assertThat(page.getTotalPages(), is(2));
|
||||
}
|
||||
|
||||
List<User> users =
|
||||
userRepository.findByEmailAddressAndLastnameOrFirstname(
|
||||
"dave@dmband.com", "Matthews", "Carter");
|
||||
@Test
|
||||
public void executesPagingMethodToListCorrectly() {
|
||||
|
||||
assertNotNull(users);
|
||||
assertEquals(2, users.size());
|
||||
assertTrue(users.contains(dave));
|
||||
assertTrue(users.contains(carter));
|
||||
}
|
||||
List<User> list = userRepository.findByFirstname("Carter", new PageRequest(0, 1));
|
||||
assertThat(list.size(), is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executesInKeywordForPageCorrectly() {
|
||||
|
||||
@Test
|
||||
public void executesPagingMethodToPageCorrectly() {
|
||||
Page<User> page = userRepository.findByFirstnameIn(new PageRequest(0, 1), "Dave", "Oliver August");
|
||||
|
||||
Page<User> page =
|
||||
userRepository
|
||||
.findByLastname(new PageRequest(0, 1), "Matthews");
|
||||
assertThat(page.getNumberOfElements(), is(1));
|
||||
assertThat(page.getTotalElements(), is(2L));
|
||||
assertThat(page.getTotalPages(), is(2));
|
||||
}
|
||||
assertThat(page.getNumberOfElements(), is(1));
|
||||
assertThat(page.getTotalElements(), is(2L));
|
||||
assertThat(page.getTotalPages(), is(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executesNotInQueryCorrectly() throws Exception {
|
||||
|
||||
@Test
|
||||
public void executesPagingMethodToListCorrectly() {
|
||||
List<User> result = userRepository.findByFirstnameNotIn(Arrays.asList("Dave", "Carter"));
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result.get(0), is(oliver));
|
||||
}
|
||||
|
||||
List<User> list =
|
||||
userRepository.findByFirstname("Carter", new PageRequest(0, 1));
|
||||
assertThat(list.size(), is(1));
|
||||
}
|
||||
@Test
|
||||
public void respectsPageableOrderOnQueryGenerateFromMethodName() throws Exception {
|
||||
|
||||
|
||||
@Test
|
||||
public void executesInKeywordForPageCorrectly() {
|
||||
|
||||
Page<User> page =
|
||||
userRepository.findByFirstnameIn(new PageRequest(0, 1), "Dave",
|
||||
"Oliver August");
|
||||
|
||||
assertThat(page.getNumberOfElements(), is(1));
|
||||
assertThat(page.getTotalElements(), is(2L));
|
||||
assertThat(page.getTotalPages(), is(2));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executesNotInQueryCorrectly() throws Exception {
|
||||
|
||||
List<User> result =
|
||||
userRepository.findByFirstnameNotIn(Arrays.asList("Dave",
|
||||
"Carter"));
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result.get(0), is(oliver));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void respectsPageableOrderOnQueryGenerateFromMethodName()
|
||||
throws Exception {
|
||||
|
||||
Page<User> ascending =
|
||||
userRepository.findByLastnameLike(new PageRequest(0, 10,
|
||||
new Sort(Direction.ASC, "firstname")), "Matthews");
|
||||
Page<User> descending =
|
||||
userRepository.findByLastnameLike(new PageRequest(0, 10,
|
||||
new Sort(Direction.DESC, "firstname")), "Matthews");
|
||||
assertThat(ascending.getTotalElements(), is(2L));
|
||||
assertThat(descending.getTotalElements(), is(2L));
|
||||
assertThat(ascending.getContent().get(0).getFirstname(),
|
||||
is(not(equalTo(descending.getContent().get(0).getFirstname()))));
|
||||
assertThat(ascending.getContent().get(0).getFirstname(),
|
||||
is(equalTo(descending.getContent().get(1).getFirstname())));
|
||||
assertThat(ascending.getContent().get(1).getFirstname(),
|
||||
is(equalTo(descending.getContent().get(0).getFirstname())));
|
||||
}
|
||||
Page<User> ascending = userRepository.findByLastnameLike(new PageRequest(0, 10,
|
||||
new Sort(Direction.ASC, "firstname")), "Matthews");
|
||||
Page<User> descending = userRepository.findByLastnameLike(new PageRequest(0, 10, new Sort(Direction.DESC,
|
||||
"firstname")), "Matthews");
|
||||
assertThat(ascending.getTotalElements(), is(2L));
|
||||
assertThat(descending.getTotalElements(), is(2L));
|
||||
assertThat(ascending.getContent().get(0).getFirstname(), is(not(equalTo(descending.getContent().get(0)
|
||||
.getFirstname()))));
|
||||
assertThat(ascending.getContent().get(0).getFirstname(), is(equalTo(descending.getContent().get(1).getFirstname())));
|
||||
assertThat(ascending.getContent().get(1).getFirstname(), is(equalTo(descending.getContent().get(0).getFirstname())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,6 @@ import org.springframework.data.jpa.repository.sample.RoleRepository;
|
||||
import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class for integration test for namespace configuration.
|
||||
*
|
||||
@@ -34,24 +33,23 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public abstract class AbstractRepositoryConfigTests {
|
||||
|
||||
@Autowired(required = false)
|
||||
UserRepository userRepository;
|
||||
@Autowired(required = false)
|
||||
UserRepository userRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
RoleRepository roleRepository;
|
||||
@Autowired(required = false)
|
||||
RoleRepository roleRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
AuditableUserRepository auditableUserRepository;
|
||||
@Autowired(required = false)
|
||||
AuditableUserRepository auditableUserRepository;
|
||||
|
||||
/**
|
||||
* Asserts that context creation detects 3 repository beans.
|
||||
*/
|
||||
@Test
|
||||
public void testContextCreation() {
|
||||
|
||||
/**
|
||||
* Asserts that context creation detects 3 repository beans.
|
||||
*/
|
||||
@Test
|
||||
public void testContextCreation() {
|
||||
|
||||
assertNotNull(userRepository);
|
||||
assertNotNull(roleRepository);
|
||||
assertNotNull(auditableUserRepository);
|
||||
}
|
||||
assertNotNull(userRepository);
|
||||
assertNotNull(roleRepository);
|
||||
assertNotNull(auditableUserRepository);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
* Integration tests for {@link AuditingBeanDefinitionParser}.
|
||||
*
|
||||
@@ -32,31 +31,25 @@ import org.springframework.core.io.ClassPathResource;
|
||||
*/
|
||||
public class AuditingBeanDefinitionParserTests {
|
||||
|
||||
@Test
|
||||
public void settingDatesIsConfigured() throws Exception {
|
||||
@Test
|
||||
public void settingDatesIsConfigured() throws Exception {
|
||||
|
||||
assertSetDatesIsSetTo("auditing/auditing-namespace-context.xml", "true");
|
||||
}
|
||||
assertSetDatesIsSetTo("auditing/auditing-namespace-context.xml", "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notSettingDatesIsConfigured() throws Exception {
|
||||
|
||||
@Test
|
||||
public void notSettingDatesIsConfigured() throws Exception {
|
||||
assertSetDatesIsSetTo("auditing/auditing-namespace-context2.xml", "false");
|
||||
}
|
||||
|
||||
assertSetDatesIsSetTo("auditing/auditing-namespace-context2.xml",
|
||||
"false");
|
||||
}
|
||||
private void assertSetDatesIsSetTo(String configFile, String value) {
|
||||
|
||||
|
||||
private void assertSetDatesIsSetTo(String configFile, String value) {
|
||||
|
||||
XmlBeanFactory factory =
|
||||
new XmlBeanFactory(new ClassPathResource(configFile));
|
||||
BeanDefinition definition =
|
||||
factory.getBeanDefinition(AuditingBeanDefinitionParser.AUDITING_ENTITY_LISTENER_CLASS_NAME);
|
||||
PropertyValue propertyValue =
|
||||
definition.getPropertyValues().getPropertyValue(
|
||||
"dateTimeForNow");
|
||||
assertThat(propertyValue, is(notNullValue()));
|
||||
assertThat((String) propertyValue.getValue(), is(value));
|
||||
}
|
||||
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource(configFile));
|
||||
BeanDefinition definition = factory
|
||||
.getBeanDefinition(AuditingBeanDefinitionParser.AUDITING_ENTITY_LISTENER_CLASS_NAME);
|
||||
PropertyValue propertyValue = definition.getPropertyValues().getPropertyValue("dateTimeForNow");
|
||||
assertThat(propertyValue, is(notNullValue()));
|
||||
assertThat((String) propertyValue.getValue(), is(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,16 +28,14 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Annotation to exclude repository interfaces from being picked up and thus in
|
||||
* consequence getting an instance being created.
|
||||
* Annotation to exclude repository interfaces from being picked up and thus in consequence getting an instance being
|
||||
* created.
|
||||
* <p>
|
||||
* This will typically be used when providing an extended base interface for all
|
||||
* repositories in combination with a custom repository base class to implement
|
||||
* methods declared in that intermediate interface. In this case you typically
|
||||
* derive your concrete repository interfaces from the intermediate one but
|
||||
* don't want to create a Spring bean for the intermediate interface.
|
||||
* This will typically be used when providing an extended base interface for all repositories in combination with a
|
||||
* custom repository base class to implement methods declared in that intermediate interface. In this case you typically
|
||||
* derive your concrete repository interfaces from the intermediate one but don't want to create a Spring bean for the
|
||||
* intermediate interface.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -45,44 +43,40 @@ import org.springframework.util.Assert;
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-customfactory-context.xml")
|
||||
public class CustomRepositoryFactoryConfigTests {
|
||||
|
||||
@Autowired(required = false)
|
||||
UserCustomExtendedRepository userRepository;
|
||||
@Autowired(required = false)
|
||||
UserCustomExtendedRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
DelegatingTransactionManager transactionManager;
|
||||
@Autowired
|
||||
DelegatingTransactionManager transactionManager;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
transactionManager.resetCount();
|
||||
}
|
||||
|
||||
transactionManager.resetCount();
|
||||
}
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testCustomFactoryUsed() {
|
||||
|
||||
Assert.notNull(userRepository);
|
||||
userRepository.customMethod(1);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testCustomFactoryUsed() {
|
||||
@Test
|
||||
public void reconfiguresTransactionalMethodWithoutGenericParameter() {
|
||||
|
||||
Assert.notNull(userRepository);
|
||||
userRepository.customMethod(1);
|
||||
}
|
||||
userRepository.findAll();
|
||||
|
||||
assertFalse(transactionManager.getDefinition().isReadOnly());
|
||||
assertThat(transactionManager.getDefinition().getTimeout(), is(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reconfiguresTransactionalMethodWithoutGenericParameter() {
|
||||
@Test
|
||||
public void reconfiguresTransactionalMethodWithGenericParameter() {
|
||||
|
||||
userRepository.findAll();
|
||||
userRepository.findOne(1);
|
||||
|
||||
assertFalse(transactionManager.getDefinition().isReadOnly());
|
||||
assertThat(transactionManager.getDefinition().getTimeout(), is(10));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void reconfiguresTransactionalMethodWithGenericParameter() {
|
||||
|
||||
userRepository.findOne(1);
|
||||
|
||||
assertFalse(transactionManager.getDefinition().isReadOnly());
|
||||
assertThat(transactionManager.getDefinition().getTimeout(), is(10));
|
||||
}
|
||||
assertFalse(transactionManager.getDefinition().isReadOnly());
|
||||
assertThat(transactionManager.getDefinition().getTimeout(), is(10));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for {@link JpaRepositoryConfigDefinitionParser}.
|
||||
*
|
||||
@@ -32,22 +31,17 @@ import org.springframework.core.io.ClassPathResource;
|
||||
*/
|
||||
public class JpaRepositoryConfigDefinitionParserTests {
|
||||
|
||||
@Test
|
||||
public void getsTransactionManagerSet() throws Exception {
|
||||
@Test
|
||||
public void getsTransactionManagerSet() throws Exception {
|
||||
|
||||
XmlBeanFactory factory =
|
||||
new XmlBeanFactory(new ClassPathResource(
|
||||
"multiple-entity-manager-integration-context.xml"));
|
||||
XmlBeanFactory factory = new XmlBeanFactory(
|
||||
new ClassPathResource("multiple-entity-manager-integration-context.xml"));
|
||||
|
||||
BeanDefinition definition =
|
||||
factory.getBeanDefinition("auditableUserRepository");
|
||||
assertThat(definition, is(notNullValue()));
|
||||
BeanDefinition definition = factory.getBeanDefinition("auditableUserRepository");
|
||||
assertThat(definition, is(notNullValue()));
|
||||
|
||||
PropertyValue transactionManager =
|
||||
definition.getPropertyValues().getPropertyValue(
|
||||
"transactionManager");
|
||||
assertThat(transactionManager, is(notNullValue()));
|
||||
assertThat(transactionManager.getValue().toString(),
|
||||
is("transactionManager-2"));
|
||||
}
|
||||
PropertyValue transactionManager = definition.getPropertyValues().getPropertyValue("transactionManager");
|
||||
assertThat(transactionManager, is(notNullValue()));
|
||||
assertThat(transactionManager.getValue().toString(), is("transactionManager-2"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for XML configuration of {@link QueryLookupStrategy.Key}s.
|
||||
*
|
||||
@@ -38,22 +37,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@ContextConfiguration(locations = "classpath:config/lookup-strategies-context.xml")
|
||||
public class QueryLookupStrategyTests {
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
/**
|
||||
* Assert that {@link QueryLookupStrategy#USE_DECLARED_QUERY} is being set on the factory if configured.
|
||||
*/
|
||||
@Test
|
||||
public void assertUseDeclaredQuery() {
|
||||
|
||||
/**
|
||||
* Assert that {@link QueryLookupStrategy#USE_DECLARED_QUERY} is being set
|
||||
* on the factory if configured.
|
||||
*/
|
||||
@Test
|
||||
public void assertUseDeclaredQuery() {
|
||||
JpaRepositoryFactoryBean<?, ?, ?> factory = context.getBean("&roleRepository", JpaRepositoryFactoryBean.class);
|
||||
|
||||
JpaRepositoryFactoryBean<?, ?, ?> factory =
|
||||
context.getBean("&roleRepository",
|
||||
JpaRepositoryFactoryBean.class);
|
||||
|
||||
assertEquals(Key.USE_DECLARED_QUERY,
|
||||
getField(factory, "queryLookupStrategyKey"));
|
||||
}
|
||||
assertEquals(Key.USE_DECLARED_QUERY, getField(factory, "queryLookupStrategyKey"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test to test repository auto configuration.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.config;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for repository namespace configuration.
|
||||
*
|
||||
|
||||
@@ -19,29 +19,26 @@ import static org.junit.Assert.*;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test to test
|
||||
* {@link org.springframework.core.type.filter.TypeFilter} integration into
|
||||
* namespace.
|
||||
* Integration test to test {@link org.springframework.core.type.filter.TypeFilter} integration into namespace.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@ContextConfiguration(locations = "classpath:config/namespace-autoconfig-typefilter-context.xml")
|
||||
public class TypeFilterConfigTest extends AbstractRepositoryConfigTests {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.config.AbstractRepositoryConfigTests
|
||||
* #testContextCreation()
|
||||
*/
|
||||
@Override
|
||||
public void testContextCreation() {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.config.AbstractRepositoryConfigTests
|
||||
* #testContextCreation()
|
||||
*/
|
||||
@Override
|
||||
public void testContextCreation() {
|
||||
|
||||
assertNotNull(userRepository);
|
||||
assertNotNull(roleRepository);
|
||||
assertNull(auditableUserRepository);
|
||||
}
|
||||
assertNotNull(userRepository);
|
||||
assertNotNull(roleRepository);
|
||||
assertNull(auditableUserRepository);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,37 +22,32 @@ import javax.persistence.EntityManager;
|
||||
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
|
||||
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Sample custom repository base class implementing common custom functionality
|
||||
* for all derived repository instances.
|
||||
* Sample custom repository base class implementing common custom functionality for all derived repository instances.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class CustomGenericJpaRepository<T, ID extends Serializable> extends
|
||||
SimpleJpaRepository<T, ID> implements CustomGenericRepository<T, ID> {
|
||||
public class CustomGenericJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements
|
||||
CustomGenericRepository<T, ID> {
|
||||
|
||||
/**
|
||||
* @param domainClass
|
||||
* @param entityManager
|
||||
*/
|
||||
public CustomGenericJpaRepository(JpaEntityInformation<T, ID> metadata,
|
||||
EntityManager entityManager) {
|
||||
/**
|
||||
* @param domainClass
|
||||
* @param entityManager
|
||||
*/
|
||||
public CustomGenericJpaRepository(JpaEntityInformation<T, ID> metadata, EntityManager entityManager) {
|
||||
|
||||
super(metadata, entityManager);
|
||||
}
|
||||
super(metadata, entityManager);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.custom.CustomGenericRepository
|
||||
* #customMethod(java.io.Serializable)
|
||||
*/
|
||||
public T customMethod(ID id) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.custom.CustomGenericRepository
|
||||
* #customMethod(java.io.Serializable)
|
||||
*/
|
||||
public T customMethod(ID id) {
|
||||
|
||||
throw new UnsupportedOperationException(
|
||||
"Forced exception for testing purposes.");
|
||||
}
|
||||
throw new UnsupportedOperationException("Forced exception for testing purposes.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,55 +26,47 @@ import org.springframework.data.jpa.repository.support.JpaEntityInformation;
|
||||
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
||||
|
||||
/**
|
||||
* Sample implementation of a custom {@link JpaRepositoryFactory} to use a
|
||||
* custom repository base class.
|
||||
* Sample implementation of a custom {@link JpaRepositoryFactory} to use a custom repository base class.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class CustomGenericJpaRepositoryFactory extends JpaRepositoryFactory {
|
||||
|
||||
/**
|
||||
* @param entityManager
|
||||
*/
|
||||
public CustomGenericJpaRepositoryFactory(EntityManager entityManager) {
|
||||
/**
|
||||
* @param entityManager
|
||||
*/
|
||||
public CustomGenericJpaRepositoryFactory(EntityManager entityManager) {
|
||||
|
||||
super(entityManager);
|
||||
}
|
||||
super(entityManager);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.GenericJpaRepositoryFactory
|
||||
* #getTargetRepository(java.lang.Class, javax.persistence.EntityManager)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager em) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.GenericJpaRepositoryFactory
|
||||
* #getTargetRepository(java.lang.Class, javax.persistence.EntityManager)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected JpaRepository<?, ?> getTargetRepository(
|
||||
RepositoryMetadata metadata, EntityManager em) {
|
||||
JpaEntityInformation<Object, Serializable> entityMetadata = mock(JpaEntityInformation.class);
|
||||
when(entityMetadata.getJavaType()).thenReturn((Class<Object>) metadata.getDomainClass());
|
||||
return new CustomGenericJpaRepository<Object, Serializable>(entityMetadata, em);
|
||||
}
|
||||
|
||||
JpaEntityInformation<Object, Serializable> entityMetadata =
|
||||
mock(JpaEntityInformation.class);
|
||||
when(entityMetadata.getJavaType()).thenReturn(
|
||||
(Class<Object>) metadata.getDomainClass());
|
||||
return new CustomGenericJpaRepository<Object, Serializable>(
|
||||
entityMetadata, em);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getRepositoryBaseClass()
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactorySupport#
|
||||
* getRepositoryBaseClass()
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
|
||||
return CustomGenericJpaRepository.class;
|
||||
}
|
||||
return CustomGenericJpaRepository.class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,25 +23,24 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
|
||||
|
||||
/**
|
||||
* {@link JpaRepositoryFactoryBean} to return a custom repository base class.
|
||||
*
|
||||
* @author Gil Markham
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class CustomGenericJpaRepositoryFactoryBean<T extends JpaRepository<Object, Serializable>>
|
||||
extends JpaRepositoryFactoryBean<T, Object, Serializable> {
|
||||
public class CustomGenericJpaRepositoryFactoryBean<T extends JpaRepository<Object, Serializable>> extends
|
||||
JpaRepositoryFactoryBean<T, Object, Serializable> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.support.
|
||||
* GenericJpaRepositoryFactoryBean#getFactory()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.support.
|
||||
* GenericJpaRepositoryFactoryBean#getFactory()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
|
||||
|
||||
return new CustomGenericJpaRepositoryFactory(em);
|
||||
}
|
||||
return new CustomGenericJpaRepositoryFactory(em);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,27 +18,24 @@ package org.springframework.data.jpa.repository.custom;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
/**
|
||||
* Extension of {@link CrudRepository} to be added on a custom repository base
|
||||
* class. This tests the facility to implement custom base class functionality
|
||||
* for all repository instances derived from this interface and implementation
|
||||
* Extension of {@link CrudRepository} to be added on a custom repository base class. This tests the facility to
|
||||
* implement custom base class functionality for all repository instances derived from this interface and implementation
|
||||
* base class.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@NoRepositoryBean
|
||||
public interface CustomGenericRepository<T, ID extends Serializable> extends
|
||||
JpaRepository<T, ID> {
|
||||
public interface CustomGenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
|
||||
|
||||
/**
|
||||
* Custom sample method.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
T customMethod(ID id);
|
||||
/**
|
||||
* Custom sample method.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
T customMethod(ID id);
|
||||
}
|
||||
|
||||
@@ -20,28 +20,24 @@ import java.util.List;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Custom Extended repository interface for a {@code User}. This relies on the
|
||||
* custom intermediate repository interface {@link CustomGenericRepository}.
|
||||
* Custom Extended repository interface for a {@code User}. This relies on the custom intermediate repository interface
|
||||
* {@link CustomGenericRepository}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface UserCustomExtendedRepository extends
|
||||
CustomGenericRepository<User, Integer> {
|
||||
public interface UserCustomExtendedRepository extends CustomGenericRepository<User, Integer> {
|
||||
|
||||
/**
|
||||
* Sample method to test reconfiguring transactions on CRUD methods in
|
||||
* combination with custom factory.
|
||||
*
|
||||
* @see #421
|
||||
*/
|
||||
/**
|
||||
* Sample method to test reconfiguring transactions on CRUD methods in combination with custom factory.
|
||||
*
|
||||
* @see #421
|
||||
*/
|
||||
|
||||
@Transactional(readOnly = false, timeout = 10)
|
||||
List<User> findAll();
|
||||
@Transactional(readOnly = false, timeout = 10)
|
||||
List<User> findAll();
|
||||
|
||||
|
||||
@Transactional(readOnly = false, timeout = 10)
|
||||
User findOne(Integer id);
|
||||
@Transactional(readOnly = false, timeout = 10)
|
||||
User findOne(Integer id);
|
||||
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryExecution}.
|
||||
*
|
||||
@@ -38,88 +37,79 @@ import org.springframework.data.jpa.repository.query.JpaQueryExecution.Modifying
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaQueryExecutionUnitTests {
|
||||
|
||||
@Mock
|
||||
EntityManager em;
|
||||
@Mock
|
||||
AbstractStringBasedJpaQuery jpaQuery;
|
||||
@Mock
|
||||
Query query;
|
||||
@Mock
|
||||
JpaQueryMethod method;
|
||||
@Mock
|
||||
EntityManager em;
|
||||
@Mock
|
||||
AbstractStringBasedJpaQuery jpaQuery;
|
||||
@Mock
|
||||
Query query;
|
||||
@Mock
|
||||
JpaQueryMethod method;
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullQuery() {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullQuery() {
|
||||
new StubQueryExecution().execute(null, new Object[] {});
|
||||
}
|
||||
|
||||
new StubQueryExecution().execute(null, new Object[] {});
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullBinder() throws Exception {
|
||||
|
||||
new StubQueryExecution().execute(jpaQuery, null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullBinder() throws Exception {
|
||||
@Test
|
||||
public void transformsNoResultExceptionToNull() {
|
||||
|
||||
new StubQueryExecution().execute(jpaQuery, null);
|
||||
}
|
||||
assertThat(new JpaQueryExecution() {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
@Test
|
||||
public void transformsNoResultExceptionToNull() {
|
||||
return null;
|
||||
}
|
||||
}.execute(jpaQuery, new Object[] {}), is(nullValue()));
|
||||
}
|
||||
|
||||
assertThat(new JpaQueryExecution() {
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void modifyingExecutionClearsEntityManagerIfSet() {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
when(query.executeUpdate()).thenReturn(0);
|
||||
when(method.getReturnType()).thenReturn((Class) void.class);
|
||||
when(jpaQuery.createQuery(Mockito.any(Object[].class))).thenReturn(query);
|
||||
|
||||
return null;
|
||||
}
|
||||
}.execute(jpaQuery, new Object[] {}), is(nullValue()));
|
||||
}
|
||||
ModifyingExecution execution = new ModifyingExecution(method, em);
|
||||
execution.execute(jpaQuery, new Object[] {});
|
||||
|
||||
verify(em, times(1)).clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void modifyingExecutionClearsEntityManagerIfSet() {
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void allowsMethodReturnTypesForModifyingQuery() throws Exception {
|
||||
|
||||
when(query.executeUpdate()).thenReturn(0);
|
||||
when(method.getReturnType()).thenReturn((Class) void.class);
|
||||
when(jpaQuery.createQuery(Mockito.any(Object[].class))).thenReturn(
|
||||
query);
|
||||
when(method.getReturnType()).thenReturn((Class) void.class, (Class) int.class, (Class) Integer.class);
|
||||
|
||||
ModifyingExecution execution = new ModifyingExecution(method, em);
|
||||
execution.execute(jpaQuery, new Object[] {});
|
||||
new ModifyingExecution(method, em);
|
||||
new ModifyingExecution(method, em);
|
||||
new ModifyingExecution(method, em);
|
||||
}
|
||||
|
||||
verify(em, times(1)).clear();
|
||||
}
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void modifyingExecutionRejectsNonIntegerOrVoidReturnType() throws Exception {
|
||||
|
||||
when(method.getReturnType()).thenReturn((Class) Long.class);
|
||||
new ModifyingExecution(method, em);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void allowsMethodReturnTypesForModifyingQuery() throws Exception {
|
||||
static class StubQueryExecution extends JpaQueryExecution {
|
||||
|
||||
when(method.getReturnType()).thenReturn((Class) void.class,
|
||||
(Class) int.class, (Class) Integer.class);
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
new ModifyingExecution(method, em);
|
||||
new ModifyingExecution(method, em);
|
||||
new ModifyingExecution(method, em);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void modifyingExecutionRejectsNonIntegerOrVoidReturnType()
|
||||
throws Exception {
|
||||
|
||||
when(method.getReturnType()).thenReturn((Class) Long.class);
|
||||
new ModifyingExecution(method, em);
|
||||
}
|
||||
|
||||
static class StubQueryExecution extends JpaQueryExecution {
|
||||
|
||||
@Override
|
||||
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.QueryMethod.Type;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryMethod}.
|
||||
*
|
||||
@@ -48,230 +47,175 @@ import org.springframework.data.repository.query.QueryMethod.Type;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaQueryMethodUnitTests {
|
||||
|
||||
static final Class<?> DOMAIN_CLASS = User.class;
|
||||
static final String METHOD_NAME = "findByFirstname";
|
||||
static final Class<?> DOMAIN_CLASS = User.class;
|
||||
static final String METHOD_NAME = "findByFirstname";
|
||||
|
||||
@Mock
|
||||
QueryExtractor extractor;
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
@Mock
|
||||
QueryExtractor extractor;
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
|
||||
Method repositoryMethod, invalidReturnType, pageableAndSort, pageableTwice,
|
||||
sortableTwice, modifyingMethod;
|
||||
Method repositoryMethod, invalidReturnType, pageableAndSort, pageableTwice, sortableTwice, modifyingMethod;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
repositoryMethod = UserRepository.class.getMethod("findByLastname", String.class);
|
||||
|
||||
repositoryMethod =
|
||||
UserRepository.class.getMethod("findByLastname", String.class);
|
||||
invalidReturnType = InvalidRepository.class.getMethod(METHOD_NAME, String.class, Pageable.class);
|
||||
pageableAndSort = InvalidRepository.class.getMethod(METHOD_NAME, String.class, Pageable.class, Sort.class);
|
||||
pageableTwice = InvalidRepository.class.getMethod(METHOD_NAME, String.class, Pageable.class, Pageable.class);
|
||||
|
||||
invalidReturnType =
|
||||
InvalidRepository.class.getMethod(METHOD_NAME, String.class,
|
||||
Pageable.class);
|
||||
pageableAndSort =
|
||||
InvalidRepository.class.getMethod(METHOD_NAME, String.class,
|
||||
Pageable.class, Sort.class);
|
||||
pageableTwice =
|
||||
InvalidRepository.class.getMethod(METHOD_NAME, String.class,
|
||||
Pageable.class, Pageable.class);
|
||||
sortableTwice = InvalidRepository.class.getMethod(METHOD_NAME, String.class, Sort.class, Sort.class);
|
||||
modifyingMethod = UserRepository.class.getMethod("renameAllUsersTo", String.class);
|
||||
}
|
||||
|
||||
sortableTwice =
|
||||
InvalidRepository.class.getMethod(METHOD_NAME, String.class,
|
||||
Sort.class, Sort.class);
|
||||
modifyingMethod =
|
||||
UserRepository.class
|
||||
.getMethod("renameAllUsersTo", String.class);
|
||||
}
|
||||
@Test
|
||||
public void testname() {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
|
||||
@Test
|
||||
public void testname() {
|
||||
assertEquals("User.findByLastname", method.getNamedQueryName());
|
||||
assertThat(method.getType(), is(Type.COLLECTION));
|
||||
}
|
||||
|
||||
JpaQueryMethod method =
|
||||
new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullRepositoryMethod() {
|
||||
|
||||
assertEquals("User.findByLastname", method.getNamedQueryName());
|
||||
assertThat(method.getType(), is(Type.COLLECTION));
|
||||
}
|
||||
new JpaQueryMethod(null, metadata, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullQueryExtractor() {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullRepositoryMethod() {
|
||||
new JpaQueryMethod(repositoryMethod, metadata, null);
|
||||
}
|
||||
|
||||
new JpaQueryMethod(null, metadata, extractor);
|
||||
}
|
||||
@Test
|
||||
public void returnsCorrectName() {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
assertEquals(repositoryMethod.getName(), method.getName());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullQueryExtractor() {
|
||||
@Test
|
||||
public void returnsQueryIfAvailable() throws Exception {
|
||||
|
||||
new JpaQueryMethod(repositoryMethod, metadata, null);
|
||||
}
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
|
||||
assertNull(method.getAnnotatedQuery());
|
||||
|
||||
@Test
|
||||
public void returnsCorrectName() {
|
||||
Method repositoryMethod = UserRepository.class.getMethod("findByAnnotatedQuery", String.class);
|
||||
|
||||
JpaQueryMethod method =
|
||||
new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
assertEquals(repositoryMethod.getName(), method.getName());
|
||||
}
|
||||
assertNotNull(new JpaQueryMethod(repositoryMethod, metadata, extractor).getAnnotatedQuery());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvalidReturntypeOnPagebleFinder() {
|
||||
|
||||
@Test
|
||||
public void returnsQueryIfAvailable() throws Exception {
|
||||
new JpaQueryMethod(invalidReturnType, metadata, extractor);
|
||||
}
|
||||
|
||||
JpaQueryMethod method =
|
||||
new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsPageableAndSortInFinderMethod() {
|
||||
|
||||
assertNull(method.getAnnotatedQuery());
|
||||
new JpaQueryMethod(pageableAndSort, metadata, extractor);
|
||||
}
|
||||
|
||||
Method repositoryMethod =
|
||||
UserRepository.class.getMethod("findByAnnotatedQuery",
|
||||
String.class);
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsTwoPageableParameters() {
|
||||
|
||||
assertNotNull(new JpaQueryMethod(repositoryMethod, metadata, extractor)
|
||||
.getAnnotatedQuery());
|
||||
}
|
||||
new JpaQueryMethod(pageableTwice, metadata, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsTwoSortableParameters() {
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvalidReturntypeOnPagebleFinder() {
|
||||
new JpaQueryMethod(sortableTwice, metadata, extractor);
|
||||
}
|
||||
|
||||
new JpaQueryMethod(invalidReturnType, metadata, extractor);
|
||||
}
|
||||
@Test
|
||||
public void recognizesModifyingMethod() {
|
||||
|
||||
JpaQueryMethod method = new JpaQueryMethod(modifyingMethod, metadata, extractor);
|
||||
assertTrue(method.isModifyingQuery());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsPageableAndSortInFinderMethod() {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsModifyingMethodWithPageable() throws Exception {
|
||||
|
||||
new JpaQueryMethod(pageableAndSort, metadata, extractor);
|
||||
}
|
||||
Method method = InvalidRepository.class.getMethod("updateMethod", String.class, Pageable.class);
|
||||
|
||||
new JpaQueryMethod(method, metadata, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsTwoPageableParameters() {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsModifyingMethodWithSort() throws Exception {
|
||||
|
||||
new JpaQueryMethod(pageableTwice, metadata, extractor);
|
||||
}
|
||||
Method method = InvalidRepository.class.getMethod("updateMethod", String.class, Sort.class);
|
||||
|
||||
new JpaQueryMethod(method, metadata, extractor);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsTwoSortableParameters() {
|
||||
@Test
|
||||
public void discoversHintsCorrectly() {
|
||||
|
||||
new JpaQueryMethod(sortableTwice, metadata, extractor);
|
||||
}
|
||||
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
List<QueryHint> hints = method.getHints();
|
||||
|
||||
assertNotNull(hints);
|
||||
assertThat(hints.get(0).name(), is("foo"));
|
||||
assertThat(hints.get(0).value(), is("bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recognizesModifyingMethod() {
|
||||
@Test
|
||||
public void calculatesNamedQueryNamesCorrectly() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
JpaQueryMethod method =
|
||||
new JpaQueryMethod(modifyingMethod, metadata, extractor);
|
||||
assertTrue(method.isModifyingQuery());
|
||||
}
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
assertThat(queryMethod.getNamedQueryName(), is("User.findByLastname"));
|
||||
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);
|
||||
Method method = UserRepository.class.getMethod("renameAllUsersTo", String.class);
|
||||
queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
assertThat(queryMethod.getNamedQueryName(), is("User.renameAllUsersTo"));
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsModifyingMethodWithPageable() throws Exception {
|
||||
method = UserRepository.class.getMethod("findSpecialUsersByLastname", String.class);
|
||||
queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
assertThat(queryMethod.getNamedQueryName(), is("SpecialUser.findSpecialUsersByLastname"));
|
||||
}
|
||||
|
||||
Method method =
|
||||
InvalidRepository.class.getMethod("updateMethod", String.class,
|
||||
Pageable.class);
|
||||
/**
|
||||
* Interface to define invalid repository methods for testing.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static interface InvalidRepository {
|
||||
|
||||
new JpaQueryMethod(method, metadata, extractor);
|
||||
}
|
||||
// Invalid return type
|
||||
User findByFirstname(String firstname, Pageable pageable);
|
||||
|
||||
// Should not use Pageable *and* Sort
|
||||
Page<User> findByFirstname(String firstname, Pageable pageable, Sort sort);
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsModifyingMethodWithSort() throws Exception {
|
||||
// Must not use two Pageables
|
||||
Page<User> findByFirstname(String firstname, Pageable first, Pageable second);
|
||||
|
||||
Method method =
|
||||
InvalidRepository.class.getMethod("updateMethod", String.class,
|
||||
Sort.class);
|
||||
// Must not use two Pageables
|
||||
Page<User> findByFirstname(String firstname, Sort first, Sort second);
|
||||
|
||||
new JpaQueryMethod(method, metadata, extractor);
|
||||
}
|
||||
// Not backed by a named query or @Query annotation
|
||||
@Modifying
|
||||
void updateMethod(String firstname);
|
||||
|
||||
// Modifying and Pageable is not allowed
|
||||
@Modifying
|
||||
Page<String> updateMethod(String firstname, Pageable pageable);
|
||||
|
||||
@Test
|
||||
public void discoversHintsCorrectly() {
|
||||
|
||||
JpaQueryMethod method =
|
||||
new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
List<QueryHint> hints = method.getHints();
|
||||
|
||||
assertNotNull(hints);
|
||||
assertThat(hints.get(0).name(), is("foo"));
|
||||
assertThat(hints.get(0).value(), is("bar"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void calculatesNamedQueryNamesCorrectly() throws SecurityException,
|
||||
NoSuchMethodException {
|
||||
|
||||
JpaQueryMethod queryMethod =
|
||||
new JpaQueryMethod(repositoryMethod, metadata, extractor);
|
||||
assertThat(queryMethod.getNamedQueryName(), is("User.findByLastname"));
|
||||
|
||||
RepositoryMetadata metadata =
|
||||
new DefaultRepositoryMetadata(UserRepository.class);
|
||||
Method method =
|
||||
UserRepository.class
|
||||
.getMethod("renameAllUsersTo", String.class);
|
||||
queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
assertThat(queryMethod.getNamedQueryName(), is("User.renameAllUsersTo"));
|
||||
|
||||
method =
|
||||
UserRepository.class.getMethod("findSpecialUsersByLastname",
|
||||
String.class);
|
||||
queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
assertThat(queryMethod.getNamedQueryName(),
|
||||
is("SpecialUser.findSpecialUsersByLastname"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to define invalid repository methods for testing.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static interface InvalidRepository {
|
||||
|
||||
// Invalid return type
|
||||
User findByFirstname(String firstname, Pageable pageable);
|
||||
|
||||
|
||||
// Should not use Pageable *and* Sort
|
||||
Page<User> findByFirstname(String firstname, Pageable pageable,
|
||||
Sort sort);
|
||||
|
||||
|
||||
// Must not use two Pageables
|
||||
Page<User> findByFirstname(String firstname, Pageable first,
|
||||
Pageable second);
|
||||
|
||||
|
||||
// Must not use two Pageables
|
||||
Page<User> findByFirstname(String firstname, Sort first, Sort second);
|
||||
|
||||
|
||||
// Not backed by a named query or @Query annotation
|
||||
@Modifying
|
||||
void updateMethod(String firstname);
|
||||
|
||||
|
||||
// Modifying and Pageable is not allowed
|
||||
@Modifying
|
||||
Page<String> updateMethod(String firstname, Pageable pageable);
|
||||
|
||||
|
||||
// Modifying and Sort is not allowed
|
||||
@Modifying
|
||||
void updateMethod(String firstname, Sort sort);
|
||||
}
|
||||
// Modifying and Sort is not allowed
|
||||
@Modifying
|
||||
void updateMethod(String firstname, Sort sort);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryCreationException;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link NamedQuery}.
|
||||
*
|
||||
@@ -40,37 +39,34 @@ import org.springframework.data.repository.query.QueryCreationException;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class NamedQueryUnitTests {
|
||||
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
@Mock
|
||||
QueryExtractor extractor;
|
||||
@Mock
|
||||
EntityManager em;
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
@Mock
|
||||
QueryExtractor extractor;
|
||||
@Mock
|
||||
EntityManager em;
|
||||
|
||||
Method method;
|
||||
Method method;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
@Before
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
method = SampleRepository.class.getMethod("foo", Pageable.class);
|
||||
when(metadata.getDomainClass()).thenReturn((Class) String.class);
|
||||
}
|
||||
|
||||
method = SampleRepository.class.getMethod("foo", Pageable.class);
|
||||
when(metadata.getDomainClass()).thenReturn((Class) String.class);
|
||||
}
|
||||
@Test(expected = QueryCreationException.class)
|
||||
public void rejectsPersistenceProviderIfIncapableOfExtractingQueriesAndPagebleBeingUsed() {
|
||||
|
||||
when(extractor.canExtractQuery()).thenReturn(false);
|
||||
|
||||
@Test(expected = QueryCreationException.class)
|
||||
public void rejectsPersistenceProviderIfIncapableOfExtractingQueriesAndPagebleBeingUsed() {
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
NamedQuery.lookupFrom(queryMethod, em);
|
||||
}
|
||||
|
||||
when(extractor.canExtractQuery()).thenReturn(false);
|
||||
interface SampleRepository {
|
||||
|
||||
JpaQueryMethod queryMethod =
|
||||
new JpaQueryMethod(method, metadata, extractor);
|
||||
NamedQuery.lookupFrom(queryMethod, em);
|
||||
}
|
||||
|
||||
interface SampleRepository {
|
||||
|
||||
Page<String> foo(Pageable pageable);
|
||||
}
|
||||
Page<String> foo(Pageable pageable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link ParameterBinder}.
|
||||
*
|
||||
@@ -44,185 +43,146 @@ import org.springframework.data.repository.query.Parameters;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ParameterBinderUnitTests {
|
||||
|
||||
private Method valid;
|
||||
private Method valid;
|
||||
|
||||
@Mock
|
||||
private Query query;
|
||||
private Method useIndexedParameters;
|
||||
private Method indexedParametersWithSort;
|
||||
@Mock
|
||||
private Query query;
|
||||
private Method useIndexedParameters;
|
||||
private Method indexedParametersWithSort;
|
||||
|
||||
@Before
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
@Before
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
valid = SampleRepository.class.getMethod("valid", String.class);
|
||||
|
||||
valid = SampleRepository.class.getMethod("valid", String.class);
|
||||
useIndexedParameters = SampleRepository.class.getMethod("useIndexedParameters", String.class);
|
||||
indexedParametersWithSort = SampleRepository.class.getMethod("indexedParameterWithSort", String.class, Sort.class);
|
||||
}
|
||||
|
||||
useIndexedParameters =
|
||||
SampleRepository.class.getMethod("useIndexedParameters",
|
||||
String.class);
|
||||
indexedParametersWithSort =
|
||||
SampleRepository.class.getMethod("indexedParameterWithSort",
|
||||
String.class, Sort.class);
|
||||
}
|
||||
static class User {
|
||||
|
||||
static class User {
|
||||
}
|
||||
|
||||
}
|
||||
static interface SampleRepository {
|
||||
|
||||
static interface SampleRepository {
|
||||
User useIndexedParameters(String lastname);
|
||||
|
||||
User useIndexedParameters(String lastname);
|
||||
User indexedParameterWithSort(String lastname, Sort sort);
|
||||
|
||||
User valid(@Param("username") String username);
|
||||
|
||||
User indexedParameterWithSort(String lastname, Sort sort);
|
||||
User validWithPageable(@Param("username") String username, Pageable pageable);
|
||||
|
||||
User validWithSort(@Param("username") String username, Sort sort);
|
||||
}
|
||||
|
||||
User valid(@Param("username") String username);
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsToManyParameters() throws Exception {
|
||||
|
||||
new ParameterBinder(new Parameters(valid), new Object[] { "foo", "bar" });
|
||||
}
|
||||
|
||||
User validWithPageable(@Param("username") String username,
|
||||
Pageable pageable);
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullParameters() throws Exception {
|
||||
|
||||
new ParameterBinder(new Parameters(valid), (Object[]) null);
|
||||
}
|
||||
|
||||
User validWithSort(@Param("username") String username, Sort sort);
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsToLittleParameters() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
Parameters parameters = new Parameters(valid);
|
||||
new ParameterBinder(parameters);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsToManyParameters() throws Exception {
|
||||
@Test
|
||||
public void returnsNullIfNoPageableWasProvided() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
new ParameterBinder(new Parameters(valid),
|
||||
new Object[] { "foo", "bar" });
|
||||
}
|
||||
Method method = SampleRepository.class.getMethod("validWithPageable", String.class, Pageable.class);
|
||||
|
||||
Parameters parameters = new Parameters(method);
|
||||
ParameterBinder binder = new ParameterBinder(parameters, new Object[] { "foo", null });
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullParameters() throws Exception {
|
||||
assertThat(binder.getPageable(), is(nullValue()));
|
||||
}
|
||||
|
||||
new ParameterBinder(new Parameters(valid), (Object[]) null);
|
||||
}
|
||||
@Test
|
||||
public void bindWorksWithNullForSort() throws Exception {
|
||||
|
||||
Method validWithSort = SampleRepository.class.getMethod("validWithSort", String.class, Sort.class);
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsToLittleParameters() throws SecurityException,
|
||||
NoSuchMethodException {
|
||||
new ParameterBinder(new Parameters(validWithSort), new Object[] { "foo", null }).bind(query);
|
||||
verify(query).setParameter(eq(1), eq("foo"));
|
||||
}
|
||||
|
||||
Parameters parameters = new Parameters(valid);
|
||||
new ParameterBinder(parameters);
|
||||
}
|
||||
@Test
|
||||
public void bindWorksWithNullForPageable() throws Exception {
|
||||
|
||||
Method validWithPageable = SampleRepository.class.getMethod("validWithPageable", String.class, Pageable.class);
|
||||
|
||||
@Test
|
||||
public void returnsNullIfNoPageableWasProvided() throws SecurityException,
|
||||
NoSuchMethodException {
|
||||
new ParameterBinder(new Parameters(validWithPageable), new Object[] { "foo", null }).bind(query);
|
||||
verify(query).setParameter(eq(1), eq("foo"));
|
||||
}
|
||||
|
||||
Method method =
|
||||
SampleRepository.class.getMethod("validWithPageable",
|
||||
String.class, Pageable.class);
|
||||
@Test
|
||||
public void usesIndexedParametersIfNoParamAnnotationPresent() throws Exception {
|
||||
|
||||
Parameters parameters = new Parameters(method);
|
||||
ParameterBinder binder =
|
||||
new ParameterBinder(parameters, new Object[] { "foo", null });
|
||||
new ParameterBinder(new Parameters(useIndexedParameters), new Object[] { "foo" }).bind(query);
|
||||
verify(query).setParameter(eq(1), anyObject());
|
||||
}
|
||||
|
||||
assertThat(binder.getPageable(), is(nullValue()));
|
||||
}
|
||||
@Test
|
||||
public void usesParameterNameIfAnnotated() throws Exception {
|
||||
|
||||
when(query.setParameter(eq("username"), anyObject())).thenReturn(query);
|
||||
new ParameterBinder(new Parameters(valid), new Object[] { "foo" }) {
|
||||
|
||||
@Test
|
||||
public void bindWorksWithNullForSort() throws Exception {
|
||||
@Override
|
||||
boolean hasNamedParameter(Query query) {
|
||||
|
||||
Method validWithSort =
|
||||
SampleRepository.class.getMethod("validWithSort", String.class,
|
||||
Sort.class);
|
||||
return true;
|
||||
}
|
||||
}.bind(query);
|
||||
verify(query).setParameter(eq("username"), anyObject());
|
||||
}
|
||||
|
||||
new ParameterBinder(new Parameters(validWithSort), new Object[] {
|
||||
"foo", null }).bind(query);
|
||||
verify(query).setParameter(eq(1), eq("foo"));
|
||||
}
|
||||
@Test
|
||||
public void bindsEmbeddableCorrectly() throws Exception {
|
||||
|
||||
Method method = getClass().getMethod("findByEmbeddable", SampleEmbeddable.class);
|
||||
Parameters parameters = new Parameters(method);
|
||||
SampleEmbeddable embeddable = new SampleEmbeddable();
|
||||
|
||||
@Test
|
||||
public void bindWorksWithNullForPageable() throws Exception {
|
||||
new ParameterBinder(parameters, new Object[] { embeddable }).bind(query);
|
||||
|
||||
Method validWithPageable =
|
||||
SampleRepository.class.getMethod("validWithPageable",
|
||||
String.class, Pageable.class);
|
||||
verify(query).setParameter(1, embeddable);
|
||||
}
|
||||
|
||||
new ParameterBinder(new Parameters(validWithPageable), new Object[] {
|
||||
"foo", null }).bind(query);
|
||||
verify(query).setParameter(eq(1), eq("foo"));
|
||||
}
|
||||
@Test
|
||||
public void bindsSortForIndexedParameters() throws Exception {
|
||||
|
||||
Sort sort = new Sort("name");
|
||||
ParameterBinder binder = new ParameterBinder(new Parameters(indexedParametersWithSort),
|
||||
new Object[] { "name", sort });
|
||||
assertThat(binder.getSort(), is(sort));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesIndexedParametersIfNoParamAnnotationPresent()
|
||||
throws Exception {
|
||||
public SampleEntity findByEmbeddable(SampleEmbeddable embeddable) {
|
||||
|
||||
new ParameterBinder(new Parameters(useIndexedParameters),
|
||||
new Object[] { "foo" }).bind(query);
|
||||
verify(query).setParameter(eq(1), anyObject());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class SampleEntity {
|
||||
|
||||
@Test
|
||||
public void usesParameterNameIfAnnotated() throws Exception {
|
||||
private SampleEmbeddable embeddable;
|
||||
}
|
||||
|
||||
when(query.setParameter(eq("username"), anyObject())).thenReturn(query);
|
||||
new ParameterBinder(new Parameters(valid), new Object[] { "foo" }) {
|
||||
@Embeddable
|
||||
@SuppressWarnings("unused")
|
||||
public static class SampleEmbeddable {
|
||||
|
||||
@Override
|
||||
boolean hasNamedParameter(Query query) {
|
||||
|
||||
return true;
|
||||
}
|
||||
}.bind(query);
|
||||
verify(query).setParameter(eq("username"), anyObject());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void bindsEmbeddableCorrectly() throws Exception {
|
||||
|
||||
Method method =
|
||||
getClass()
|
||||
.getMethod("findByEmbeddable", SampleEmbeddable.class);
|
||||
Parameters parameters = new Parameters(method);
|
||||
SampleEmbeddable embeddable = new SampleEmbeddable();
|
||||
|
||||
new ParameterBinder(parameters, new Object[] { embeddable })
|
||||
.bind(query);
|
||||
|
||||
verify(query).setParameter(1, embeddable);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void bindsSortForIndexedParameters() throws Exception {
|
||||
|
||||
Sort sort = new Sort("name");
|
||||
ParameterBinder binder =
|
||||
new ParameterBinder(new Parameters(indexedParametersWithSort),
|
||||
new Object[] { "name", sort });
|
||||
assertThat(binder.getSort(), is(sort));
|
||||
}
|
||||
|
||||
|
||||
public SampleEntity findByEmbeddable(SampleEmbeddable embeddable) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class SampleEntity {
|
||||
|
||||
private SampleEmbeddable embeddable;
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
@SuppressWarnings("unused")
|
||||
public static class SampleEmbeddable {
|
||||
|
||||
private String foo;
|
||||
private String bar;
|
||||
}
|
||||
private String foo;
|
||||
private String bar;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Integration tests for {@link PartTreeJpaQuery}.
|
||||
*
|
||||
@@ -42,33 +41,27 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
public class PartTreeJpaQueryIntegrationTests {
|
||||
|
||||
@PersistenceContext
|
||||
EntityManager entityManager;
|
||||
@PersistenceContext
|
||||
EntityManager entityManager;
|
||||
|
||||
/**
|
||||
* @see DATADOC-90
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
|
||||
/**
|
||||
* @see DATADOC-90
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
Method method = UserRepository.class.getMethod("findByFirstname", String.class, Pageable.class);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, new DefaultRepositoryMetadata(UserRepository.class),
|
||||
PersistenceProvider.fromEntityManager(entityManager));
|
||||
PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager);
|
||||
|
||||
Method method =
|
||||
UserRepository.class.getMethod("findByFirstname", String.class,
|
||||
Pageable.class);
|
||||
JpaQueryMethod queryMethod =
|
||||
new JpaQueryMethod(method, new DefaultRepositoryMetadata(
|
||||
UserRepository.class),
|
||||
PersistenceProvider.fromEntityManager(entityManager));
|
||||
PartTreeJpaQuery jpaQuery =
|
||||
new PartTreeJpaQuery(queryMethod, entityManager);
|
||||
jpaQuery.createQuery(new Object[] { "Matthews", new PageRequest(0, 1) });
|
||||
jpaQuery.createQuery(new Object[] { "Matthews", new PageRequest(0, 1) });
|
||||
}
|
||||
|
||||
jpaQuery.createQuery(new Object[] { "Matthews", new PageRequest(0, 1) });
|
||||
jpaQuery.createQuery(new Object[] { "Matthews", new PageRequest(0, 1) });
|
||||
}
|
||||
interface UserRepository extends Repository<User, Long> {
|
||||
|
||||
interface UserRepository extends Repository<User, Long> {
|
||||
|
||||
Page<User> findByFirstname(String firstname, Pageable pageable);
|
||||
}
|
||||
Page<User> findByFirstname(String firstname, Pageable pageable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import static org.springframework.data.jpa.repository.query.QueryUtils.*;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryUtils}.
|
||||
*
|
||||
@@ -30,129 +29,109 @@ import org.junit.Test;
|
||||
*/
|
||||
public class QueryUtilsUnitTests {
|
||||
|
||||
static final String QUERY = "select u from User u";
|
||||
static final String FQ_QUERY =
|
||||
"select u from org.acme.domain.User$Foo_Bar u";
|
||||
static final String SIMPLE_QUERY = "from User u";
|
||||
static final String COUNT_QUERY = "select count(u) from User u";
|
||||
static final String QUERY = "select u from User u";
|
||||
static final String FQ_QUERY = "select u from org.acme.domain.User$Foo_Bar u";
|
||||
static final String SIMPLE_QUERY = "from User u";
|
||||
static final String COUNT_QUERY = "select count(u) from User u";
|
||||
|
||||
static final String QUERY_WITH_AS =
|
||||
"select u from User as u where u.username = ?";
|
||||
static final String QUERY_WITH_AS = "select u from User as u where u.username = ?";
|
||||
|
||||
static final Matcher<String> IS_U = is("u");
|
||||
static final Matcher<String> IS_U = is("u");
|
||||
|
||||
@Test
|
||||
public void createsCountQueryCorrectly() throws Exception {
|
||||
|
||||
@Test
|
||||
public void createsCountQueryCorrectly() throws Exception {
|
||||
assertCountQuery(QUERY, COUNT_QUERY);
|
||||
|
||||
assertCountQuery(QUERY, COUNT_QUERY);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @see #303
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueriesCorrectlyForCapitalLetterJPQL() {
|
||||
|
||||
assertCountQuery("FROM User u WHERE u.foo.bar = ?", "select count(u) FROM User u WHERE u.foo.bar = ?");
|
||||
|
||||
/**
|
||||
* @see #303
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueriesCorrectlyForCapitalLetterJPQL() {
|
||||
assertCountQuery("SELECT u FROM User u where u.foo.bar = ?", "select count(u) FROM User u where u.foo.bar = ?");
|
||||
}
|
||||
|
||||
assertCountQuery("FROM User u WHERE u.foo.bar = ?",
|
||||
"select count(u) FROM User u WHERE u.foo.bar = ?");
|
||||
/**
|
||||
* @see #351
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForDistinctQueries() throws Exception {
|
||||
|
||||
assertCountQuery("SELECT u FROM User u where u.foo.bar = ?",
|
||||
"select count(u) FROM User u where u.foo.bar = ?");
|
||||
}
|
||||
assertCountQuery("select distinct u from User u where u.foo = ?",
|
||||
"select count(distinct u) from User u where u.foo = ?");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #351
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForConstructorQueries() throws Exception {
|
||||
|
||||
/**
|
||||
* @see #351
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForDistinctQueries() throws Exception {
|
||||
assertCountQuery("select distinct new User(u.name) from User u where u.foo = ?",
|
||||
"select count(distinct u) from User u where u.foo = ?");
|
||||
}
|
||||
|
||||
assertCountQuery("select distinct u from User u where u.foo = ?",
|
||||
"select count(distinct u) from User u where u.foo = ?");
|
||||
}
|
||||
/**
|
||||
* @see #352
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForJoins() throws Exception {
|
||||
|
||||
assertCountQuery("select distinct new User(u.name) from User u left outer join u.roles r WHERE r = ?",
|
||||
"select count(distinct u) from User u left outer join u.roles r WHERE r = ?");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #351
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForConstructorQueries() throws Exception {
|
||||
/**
|
||||
* @see #352
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForQueriesWithSubSelects() throws Exception {
|
||||
|
||||
assertCountQuery(
|
||||
"select distinct new User(u.name) from User u where u.foo = ?",
|
||||
"select count(distinct u) from User u where u.foo = ?");
|
||||
}
|
||||
assertCountQuery("select u from User u left outer join u.roles r where r in (select r from Role)",
|
||||
"select count(u) from User u left outer join u.roles r where r in (select r from Role)");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #355
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForAliasesCorrectly() throws Exception {
|
||||
|
||||
/**
|
||||
* @see #352
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForJoins() throws Exception {
|
||||
assertCountQuery("select u from User as u", "select count(u) from User as u");
|
||||
}
|
||||
|
||||
assertCountQuery(
|
||||
"select distinct new User(u.name) from User u left outer join u.roles r WHERE r = ?",
|
||||
"select count(distinct u) from User u left outer join u.roles r WHERE r = ?");
|
||||
}
|
||||
@Test
|
||||
public void allowsShortJpaSyntax() throws Exception {
|
||||
|
||||
assertCountQuery(SIMPLE_QUERY, COUNT_QUERY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #352
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForQueriesWithSubSelects() throws Exception {
|
||||
@Test
|
||||
public void detectsAliasCorrectly() throws Exception {
|
||||
|
||||
assertCountQuery(
|
||||
"select u from User u left outer join u.roles r where r in (select r from Role)",
|
||||
"select count(u) from User u left outer join u.roles r where r in (select r from Role)");
|
||||
}
|
||||
assertThat(detectAlias(QUERY), IS_U);
|
||||
assertThat(detectAlias(SIMPLE_QUERY), IS_U);
|
||||
assertThat(detectAlias(COUNT_QUERY), IS_U);
|
||||
assertThat(detectAlias(QUERY_WITH_AS), IS_U);
|
||||
assertThat(detectAlias("SELECT FROM USER U"), is("U"));
|
||||
assertThat(detectAlias("select u from User u"), IS_U);
|
||||
assertThat(detectAlias("select u from com.acme.User u"), IS_U);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowsFullyQualifiedEntityNamesInQuery() {
|
||||
|
||||
/**
|
||||
* @see #355
|
||||
*/
|
||||
@Test
|
||||
public void createsCountQueryForAliasesCorrectly() throws Exception {
|
||||
assertThat(detectAlias(FQ_QUERY), IS_U);
|
||||
assertCountQuery(FQ_QUERY, "select count(u) from org.acme.domain.User$Foo_Bar u");
|
||||
}
|
||||
|
||||
assertCountQuery("select u from User as u",
|
||||
"select count(u) from User as u");
|
||||
}
|
||||
private void assertCountQuery(String originalQuery, String countQuery) {
|
||||
|
||||
|
||||
@Test
|
||||
public void allowsShortJpaSyntax() throws Exception {
|
||||
|
||||
assertCountQuery(SIMPLE_QUERY, COUNT_QUERY);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void detectsAliasCorrectly() throws Exception {
|
||||
|
||||
assertThat(detectAlias(QUERY), IS_U);
|
||||
assertThat(detectAlias(SIMPLE_QUERY), IS_U);
|
||||
assertThat(detectAlias(COUNT_QUERY), IS_U);
|
||||
assertThat(detectAlias(QUERY_WITH_AS), IS_U);
|
||||
assertThat(detectAlias("SELECT FROM USER U"), is("U"));
|
||||
assertThat(detectAlias("select u from User u"), IS_U);
|
||||
assertThat(detectAlias("select u from com.acme.User u"), IS_U);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void allowsFullyQualifiedEntityNamesInQuery() {
|
||||
|
||||
assertThat(detectAlias(FQ_QUERY), IS_U);
|
||||
assertCountQuery(FQ_QUERY,
|
||||
"select count(u) from org.acme.domain.User$Foo_Bar u");
|
||||
}
|
||||
|
||||
|
||||
private void assertCountQuery(String originalQuery, String countQuery) {
|
||||
|
||||
assertThat(createCountQueryFor(originalQuery), is(countQuery));
|
||||
}
|
||||
assertThat(createCountQueryFor(originalQuery), is(countQuery));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.springframework.data.jpa.repository.sample.UserRepository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link SimpleJpaQuery}.
|
||||
*
|
||||
@@ -48,79 +47,67 @@ import org.springframework.data.repository.query.Parameters;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SimpleJpaQueryUnitTests {
|
||||
|
||||
JpaQueryMethod method;
|
||||
JpaQueryMethod method;
|
||||
|
||||
@Mock
|
||||
EntityManager em;
|
||||
@Mock
|
||||
QueryExtractor extractor;
|
||||
@Mock
|
||||
Query query;
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
@Mock
|
||||
ParameterBinder binder;
|
||||
@Mock
|
||||
EntityManager em;
|
||||
@Mock
|
||||
QueryExtractor extractor;
|
||||
@Mock
|
||||
Query query;
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
@Mock
|
||||
ParameterBinder binder;
|
||||
|
||||
@Before
|
||||
@QueryHints(@QueryHint(name = "foo", value = "bar"))
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
@Before
|
||||
@QueryHints(@QueryHint(name = "foo", value = "bar"))
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
when(em.createQuery(anyString())).thenReturn(query);
|
||||
|
||||
when(em.createQuery(anyString())).thenReturn(query);
|
||||
Method setUp = UserRepository.class.getMethod("findByLastname", String.class);
|
||||
method = new JpaQueryMethod(setUp, metadata, extractor);
|
||||
}
|
||||
|
||||
Method setUp =
|
||||
UserRepository.class.getMethod("findByLastname", String.class);
|
||||
method = new JpaQueryMethod(setUp, metadata, extractor);
|
||||
}
|
||||
@Test
|
||||
public void appliesHintsCorrectly() throws Exception {
|
||||
|
||||
SimpleJpaQuery jpaQuery = new SimpleJpaQuery(method, em, "foobar");
|
||||
jpaQuery.createQuery(new Object[] { "gierke" });
|
||||
|
||||
@Test
|
||||
public void appliesHintsCorrectly() throws Exception {
|
||||
verify(query).setHint("foo", "bar");
|
||||
}
|
||||
|
||||
SimpleJpaQuery jpaQuery = new SimpleJpaQuery(method, em, "foobar");
|
||||
jpaQuery.createQuery(new Object[] { "gierke" });
|
||||
@Test
|
||||
public void prefersDeclaredCountQueryOverCreatingOne() throws Exception {
|
||||
|
||||
verify(query).setHint("foo", "bar");
|
||||
}
|
||||
method = mock(JpaQueryMethod.class);
|
||||
when(method.getCountQuery()).thenReturn("foo");
|
||||
when(method.getParameters()).thenReturn(
|
||||
new Parameters(SimpleJpaQueryUnitTests.class.getMethod("prefersDeclaredCountQueryOverCreatingOne")));
|
||||
when(em.createQuery("foo")).thenReturn(query);
|
||||
|
||||
SimpleJpaQuery jpaQuery = new SimpleJpaQuery(method, em, "select u from User u");
|
||||
|
||||
@Test
|
||||
public void prefersDeclaredCountQueryOverCreatingOne() throws Exception {
|
||||
assertThat(jpaQuery.createCountQuery(new Object[] {}), is(query));
|
||||
}
|
||||
|
||||
method = mock(JpaQueryMethod.class);
|
||||
when(method.getCountQuery()).thenReturn("foo");
|
||||
when(method.getParameters())
|
||||
.thenReturn(
|
||||
new Parameters(
|
||||
SimpleJpaQueryUnitTests.class
|
||||
.getMethod("prefersDeclaredCountQueryOverCreatingOne")));
|
||||
when(em.createQuery("foo")).thenReturn(query);
|
||||
/**
|
||||
* @see DATAJPA-77
|
||||
*/
|
||||
@Test
|
||||
public void doesNotApplyPaginationToCountQuery() throws Exception {
|
||||
|
||||
SimpleJpaQuery jpaQuery =
|
||||
new SimpleJpaQuery(method, em, "select u from User u");
|
||||
when(em.createQuery(Mockito.anyString())).thenReturn(query);
|
||||
|
||||
assertThat(jpaQuery.createCountQuery(new Object[] {}), is(query));
|
||||
}
|
||||
Method method = UserRepository.class.getMethod("findAllPaged", Pageable.class);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, metadata, extractor);
|
||||
|
||||
AbstractJpaQuery jpaQuery = new SimpleJpaQuery(queryMethod, em, "select u from User u");
|
||||
jpaQuery.createCountQuery(new Object[] { new PageRequest(1, 10) });
|
||||
|
||||
/**
|
||||
* @see DATAJPA-77
|
||||
*/
|
||||
@Test
|
||||
public void doesNotApplyPaginationToCountQuery() throws Exception {
|
||||
|
||||
when(em.createQuery(Mockito.anyString())).thenReturn(query);
|
||||
|
||||
Method method =
|
||||
UserRepository.class.getMethod("findAllPaged", Pageable.class);
|
||||
JpaQueryMethod queryMethod =
|
||||
new JpaQueryMethod(method, metadata, extractor);
|
||||
|
||||
AbstractJpaQuery jpaQuery =
|
||||
new SimpleJpaQuery(queryMethod, em, "select u from User u");
|
||||
jpaQuery.createCountQuery(new Object[] { new PageRequest(1, 10) });
|
||||
|
||||
verify(query, times(0)).setFirstResult(anyInt());
|
||||
verify(query, times(0)).setMaxResults(anyInt());
|
||||
}
|
||||
verify(query, times(0)).setFirstResult(anyInt());
|
||||
verify(query, times(0)).setMaxResults(anyInt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,20 +20,18 @@ import java.util.List;
|
||||
import org.springframework.data.jpa.domain.sample.AuditableUser;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Repository interface for {@code AuditableUser}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface AuditableUserRepository extends
|
||||
JpaRepository<AuditableUser, Long> {
|
||||
public interface AuditableUserRepository extends JpaRepository<AuditableUser, Long> {
|
||||
|
||||
/**
|
||||
* Returns all users with the given firstname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return all users with the given firstname.
|
||||
*/
|
||||
public List<AuditableUser> findByFirstname(final String firstname);
|
||||
/**
|
||||
* Returns all users with the given firstname.
|
||||
*
|
||||
* @param firstname
|
||||
* @return all users with the given firstname.
|
||||
*/
|
||||
public List<AuditableUser> findByFirstname(final String firstname);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.jpa.repository.sample;
|
||||
import org.springframework.data.jpa.domain.sample.Role;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
|
||||
/**
|
||||
* Typing interface for {@code Role}.
|
||||
*
|
||||
|
||||
@@ -34,188 +34,148 @@ import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Repository interface for {@code User}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface UserRepository extends JpaRepository<User, Integer>,
|
||||
JpaSpecificationExecutor<User>, UserRepositoryCustom {
|
||||
public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User>,
|
||||
UserRepositoryCustom {
|
||||
|
||||
/**
|
||||
* Retrieve users by their lastname. The finder
|
||||
* {@literal User.findByLastname} is declared in {@literal META-INF/orm.xml}
|
||||
* .
|
||||
*
|
||||
* @param lastname
|
||||
* @return all users with the given lastname
|
||||
*/
|
||||
@QueryHints({ @QueryHint(name = "foo", value = "bar") })
|
||||
List<User> findByLastname(String lastname);
|
||||
/**
|
||||
* Retrieve users by their lastname. The finder {@literal User.findByLastname} is declared in
|
||||
* {@literal META-INF/orm.xml} .
|
||||
*
|
||||
* @param lastname
|
||||
* @return all users with the given lastname
|
||||
*/
|
||||
@QueryHints({ @QueryHint(name = "foo", value = "bar") })
|
||||
List<User> findByLastname(String lastname);
|
||||
|
||||
/**
|
||||
* Redeclaration of {@link CrudRepository#findOne(java.io.Serializable)} to change transaction configuration.
|
||||
*/
|
||||
@Transactional
|
||||
public User findOne(Integer primaryKey);
|
||||
|
||||
/**
|
||||
* Redeclaration of {@link CrudRepository#findOne(java.io.Serializable)} to
|
||||
* change transaction configuration.
|
||||
*/
|
||||
@Transactional
|
||||
public User findOne(Integer primaryKey);
|
||||
/**
|
||||
* Retrieve users by their email address. The finder {@literal User.findByEmailAddress} is declared as annotation at
|
||||
* {@code User}.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @return the user with the given email address
|
||||
*/
|
||||
User findByEmailAddress(String emailAddress);
|
||||
|
||||
@Query("select u from User u ")
|
||||
Page<User> findAllPaged(Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieve users by their email address. The finder
|
||||
* {@literal User.findByEmailAddress} is declared as annotation at
|
||||
* {@code User}.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @return the user with the given email address
|
||||
*/
|
||||
User findByEmailAddress(String emailAddress);
|
||||
/**
|
||||
* Retrieves users by the given email and lastname. Acts as a dummy method declaration to test finder query creation.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @param lastname
|
||||
* @return the user with the given email address and lastname
|
||||
*/
|
||||
User findByEmailAddressAndLastname(String emailAddress, String lastname);
|
||||
|
||||
/**
|
||||
* Retrieves users by email address and lastname or firstname. Acts as a dummy method declaration to test finder query
|
||||
* creation.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @param lastname
|
||||
* @param username
|
||||
* @return the users with the given email address and lastname or the given firstname
|
||||
*/
|
||||
List<User> findByEmailAddressAndLastnameOrFirstname(String emailAddress, String lastname, String username);
|
||||
|
||||
@Query("select u from User u ")
|
||||
Page<User> findAllPaged(Pageable pageable);
|
||||
/**
|
||||
* Retrieves a user by its username using the query annotated to the method.
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
@Query("select u from User u where u.emailAddress = ?1")
|
||||
@Transactional(readOnly = true)
|
||||
User findByAnnotatedQuery(String emailAddress);
|
||||
|
||||
/**
|
||||
* Method to directly create query from and adding a {@link Pageable} parameter to be regarded on query execution.
|
||||
*
|
||||
* @param pageable
|
||||
* @param lastname
|
||||
* @return
|
||||
*/
|
||||
Page<User> findByLastname(Pageable pageable, String lastname);
|
||||
|
||||
/**
|
||||
* Retrieves users by the given email and lastname. Acts as a dummy method
|
||||
* declaration to test finder query creation.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @param lastname
|
||||
* @return the user with the given email address and lastname
|
||||
*/
|
||||
User findByEmailAddressAndLastname(String emailAddress, String lastname);
|
||||
/**
|
||||
* Method to directly create query from and adding a {@link Pageable} parameter to be regarded on query execution.
|
||||
* Just returns the queried {@link Page}'s contents.
|
||||
*
|
||||
* @param firstname
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
List<User> findByFirstname(String firstname, Pageable pageable);
|
||||
|
||||
Page<User> findByFirstnameIn(Pageable pageable, String... firstnames);
|
||||
|
||||
/**
|
||||
* Retrieves users by email address and lastname or firstname. Acts as a
|
||||
* dummy method declaration to test finder query creation.
|
||||
*
|
||||
* @param emailAddress
|
||||
* @param lastname
|
||||
* @param username
|
||||
* @return the users with the given email address and lastname or the given
|
||||
* firstname
|
||||
*/
|
||||
List<User> findByEmailAddressAndLastnameOrFirstname(String emailAddress,
|
||||
String lastname, String username);
|
||||
List<User> findByFirstnameNotIn(Collection<String> firstnames);
|
||||
|
||||
/**
|
||||
* Manipulating query to set all {@link User}'s names to the given one.
|
||||
*
|
||||
* @param lastname
|
||||
*/
|
||||
@Modifying
|
||||
@Query("update User u set u.lastname = ?1")
|
||||
void renameAllUsersTo(String lastname);
|
||||
|
||||
/**
|
||||
* Retrieves a user by its username using the query annotated to the method.
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
@Query("select u from User u where u.emailAddress = ?1")
|
||||
@Transactional(readOnly = true)
|
||||
User findByAnnotatedQuery(String emailAddress);
|
||||
@Query("select count(u) from User u where u.firstname = ?1")
|
||||
Long countWithFirstname(String firstname);
|
||||
|
||||
/**
|
||||
* Method where parameters will be applied by name. Note that the order of the parameters is then not crucial anymore.
|
||||
*
|
||||
* @param firstname
|
||||
* @param lastname
|
||||
* @return
|
||||
*/
|
||||
@Query("select u from User u where u.lastname = :lastname or u.firstname = :firstname")
|
||||
List<User> findByLastnameOrFirstname(@Param("firstname") String foo, @Param("lastname") String bar);
|
||||
|
||||
/**
|
||||
* Method to directly create query from and adding a {@link Pageable}
|
||||
* parameter to be regarded on query execution.
|
||||
*
|
||||
* @param pageable
|
||||
* @param lastname
|
||||
* @return
|
||||
*/
|
||||
Page<User> findByLastname(Pageable pageable, String lastname);
|
||||
@Query("select u from User u where u.lastname = :lastname or u.firstname = :firstname")
|
||||
List<User> findByLastnameOrFirstnameUnannotated(String firstname, String lastname);
|
||||
|
||||
/**
|
||||
* Method to check query creation and named parameter usage go well hand in hand.
|
||||
*
|
||||
* @param lastname
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
List<User> findByFirstnameOrLastname(@Param("lastname") String lastname, @Param("firstname") String firstname);
|
||||
|
||||
/**
|
||||
* Method to directly create query from and adding a {@link Pageable}
|
||||
* parameter to be regarded on query execution. Just returns the queried
|
||||
* {@link Page}'s contents.
|
||||
*
|
||||
* @param firstname
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
List<User> findByFirstname(String firstname, Pageable pageable);
|
||||
List<User> findByLastnameLikeOrderByFirstnameDesc(String lastname);
|
||||
|
||||
List<User> findByLastnameNotLike(String lastname);
|
||||
|
||||
Page<User> findByFirstnameIn(Pageable pageable, String... firstnames);
|
||||
List<User> findByLastnameNot(String lastname);
|
||||
|
||||
List<User> findByManagerLastname(String name);
|
||||
|
||||
List<User> findByFirstnameNotIn(Collection<String> firstnames);
|
||||
List<User> findByColleaguesLastname(String lastname);
|
||||
|
||||
List<User> findByLastnameNotNull();
|
||||
|
||||
/**
|
||||
* Manipulating query to set all {@link User}'s names to the given one.
|
||||
*
|
||||
* @param lastname
|
||||
*/
|
||||
@Modifying
|
||||
@Query("update User u set u.lastname = ?1")
|
||||
void renameAllUsersTo(String lastname);
|
||||
List<User> findByLastnameNull();
|
||||
|
||||
List<User> findByEmailAddressLike(String email, Sort sort);
|
||||
|
||||
@Query("select count(u) from User u where u.firstname = ?1")
|
||||
Long countWithFirstname(String firstname);
|
||||
List<SpecialUser> findSpecialUsersByLastname(String lastname);
|
||||
|
||||
List<User> findBySpringDataNamedQuery(String lastname);
|
||||
|
||||
/**
|
||||
* Method where parameters will be applied by name. Note that the order of
|
||||
* the parameters is then not crucial anymore.
|
||||
*
|
||||
* @param firstname
|
||||
* @param lastname
|
||||
* @return
|
||||
*/
|
||||
@Query("select u from User u where u.lastname = :lastname or u.firstname = :firstname")
|
||||
List<User> findByLastnameOrFirstname(@Param("firstname") String foo,
|
||||
@Param("lastname") String bar);
|
||||
|
||||
|
||||
@Query("select u from User u where u.lastname = :lastname or u.firstname = :firstname")
|
||||
List<User> findByLastnameOrFirstnameUnannotated(String firstname,
|
||||
String lastname);
|
||||
|
||||
|
||||
/**
|
||||
* Method to check query creation and named parameter usage go well hand in
|
||||
* hand.
|
||||
*
|
||||
* @param lastname
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
List<User> findByFirstnameOrLastname(@Param("lastname") String lastname,
|
||||
@Param("firstname") String firstname);
|
||||
|
||||
|
||||
List<User> findByLastnameLikeOrderByFirstnameDesc(String lastname);
|
||||
|
||||
|
||||
List<User> findByLastnameNotLike(String lastname);
|
||||
|
||||
|
||||
List<User> findByLastnameNot(String lastname);
|
||||
|
||||
|
||||
List<User> findByManagerLastname(String name);
|
||||
|
||||
|
||||
List<User> findByColleaguesLastname(String lastname);
|
||||
|
||||
|
||||
List<User> findByLastnameNotNull();
|
||||
|
||||
|
||||
List<User> findByLastnameNull();
|
||||
|
||||
|
||||
List<User> findByEmailAddressLike(String email, Sort sort);
|
||||
|
||||
|
||||
List<SpecialUser> findSpecialUsersByLastname(String lastname);
|
||||
|
||||
|
||||
List<User> findBySpringDataNamedQuery(String lastname);
|
||||
|
||||
|
||||
Page<User> findByLastnameLike(Pageable pageable, String lastname);
|
||||
Page<User> findByLastnameLike(Pageable pageable, String lastname);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.sample;
|
||||
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
|
||||
|
||||
/**
|
||||
* Simple interface for custom methods on the repository for {@code User}s.
|
||||
*
|
||||
@@ -25,16 +24,15 @@ import org.springframework.data.jpa.domain.sample.User;
|
||||
*/
|
||||
public interface UserRepositoryCustom {
|
||||
|
||||
/**
|
||||
* Method actually triggering a finder but being overridden.
|
||||
*/
|
||||
void findByOverrridingMethod();
|
||||
/**
|
||||
* Method actually triggering a finder but being overridden.
|
||||
*/
|
||||
void findByOverrridingMethod();
|
||||
|
||||
|
||||
/**
|
||||
* Some custom method to implement.
|
||||
*
|
||||
* @param user
|
||||
*/
|
||||
void someCustomMethod(User user);
|
||||
/**
|
||||
* Some custom method to implement.
|
||||
*
|
||||
* @param user
|
||||
*/
|
||||
void someCustomMethod(User user);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
|
||||
|
||||
/**
|
||||
* Dummy implementation to allow check for invoking a custom implementation.
|
||||
*
|
||||
@@ -27,30 +26,27 @@ import org.springframework.data.jpa.domain.sample.User;
|
||||
*/
|
||||
public class UserRepositoryImpl implements UserRepositoryCustom {
|
||||
|
||||
private static final Logger LOG = LoggerFactory
|
||||
.getLogger(UserRepositoryImpl.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UserRepositoryImpl.class);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.sample.UserRepositoryCustom#
|
||||
* someCustomMethod(org.springframework.data.jpa.domain.sample.User)
|
||||
*/
|
||||
public void someCustomMethod(User u) {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.sample.UserRepositoryCustom#
|
||||
* someCustomMethod(org.springframework.data.jpa.domain.sample.User)
|
||||
*/
|
||||
public void someCustomMethod(User u) {
|
||||
LOG.debug("Some custom method was invoked!");
|
||||
}
|
||||
|
||||
LOG.debug("Some custom method was invoked!");
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.sample.UserRepositoryCustom#
|
||||
* findByOverrridingMethod()
|
||||
*/
|
||||
public void findByOverrridingMethod() {
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.sample.UserRepositoryCustom#
|
||||
* findByOverrridingMethod()
|
||||
*/
|
||||
public void findByOverrridingMethod() {
|
||||
|
||||
LOG.debug("A method overriding a finder was invoked!");
|
||||
}
|
||||
LOG.debug("A method overriding a finder was invoked!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,8 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Assures the injected repository instances are wired to the customly
|
||||
* configured {@link EntityManagerFactory}.
|
||||
* Assures the injected repository instances are wired to the customly configured {@link EntityManagerFactory}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -39,26 +37,23 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@ContextConfiguration(locations = "classpath:multiple-entity-manager-integration-context.xml")
|
||||
public class EntityManagerFactoryRefTests {
|
||||
|
||||
@Autowired
|
||||
UserRepository userRepository;
|
||||
@Autowired
|
||||
UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
AuditableUserRepository auditableUserRepository;
|
||||
@Autowired
|
||||
AuditableUserRepository auditableUserRepository;
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void useUserRepository() throws Exception {
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void useUserRepository() throws Exception {
|
||||
userRepository.saveAndFlush(new User("firstname", "lastname", "foo@bar.de"));
|
||||
}
|
||||
|
||||
userRepository.saveAndFlush(new User("firstname", "lastname",
|
||||
"foo@bar.de"));
|
||||
}
|
||||
@Test
|
||||
@Transactional("transactionManager-2")
|
||||
public void useAuditableUserRepository() throws Exception {
|
||||
|
||||
|
||||
@Test
|
||||
@Transactional("transactionManager-2")
|
||||
public void useAuditableUserRepository() throws Exception {
|
||||
|
||||
auditableUserRepository.saveAndFlush(new AuditableUser());
|
||||
}
|
||||
auditableUserRepository.saveAndFlush(new AuditableUser());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,47 +26,36 @@ import org.springframework.beans.factory.config.BeanReference;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
* Assures the injected repository instances are wired to the customly
|
||||
* configured {@link EntityManagerFactory}.
|
||||
* Assures the injected repository instances are wired to the customly configured {@link EntityManagerFactory}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class EntityManagerFactoryRefUnitTests {
|
||||
|
||||
@Test
|
||||
public void repositoriesGetTheSecondEntityManagerFactoryInjected2() {
|
||||
@Test
|
||||
public void repositoriesGetTheSecondEntityManagerFactoryInjected2() {
|
||||
|
||||
XmlBeanFactory factory =
|
||||
new XmlBeanFactory(new ClassPathResource(
|
||||
"multiple-entity-manager-context.xml"));
|
||||
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("multiple-entity-manager-context.xml"));
|
||||
|
||||
BeanDefinition bean = factory.getBeanDefinition("userRepository");
|
||||
Object value = getPropertyValue(bean, "entityManager");
|
||||
assertTrue(value instanceof BeanDefinition);
|
||||
BeanDefinition emCreator = (BeanDefinition) value;
|
||||
BeanDefinition bean = factory.getBeanDefinition("userRepository");
|
||||
Object value = getPropertyValue(bean, "entityManager");
|
||||
assertTrue(value instanceof BeanDefinition);
|
||||
BeanDefinition emCreator = (BeanDefinition) value;
|
||||
|
||||
BeanReference reference = getConstructorBeanReference(emCreator, 0);
|
||||
assertThat(reference.getBeanName(), is("secondEntityManagerFactory"));
|
||||
}
|
||||
BeanReference reference = getConstructorBeanReference(emCreator, 0);
|
||||
assertThat(reference.getBeanName(), is("secondEntityManagerFactory"));
|
||||
}
|
||||
|
||||
private Object getPropertyValue(BeanDefinition definition, String propertyName) {
|
||||
|
||||
private Object getPropertyValue(BeanDefinition definition,
|
||||
String propertyName) {
|
||||
return definition.getPropertyValues().getPropertyValue(propertyName).getValue();
|
||||
}
|
||||
|
||||
return definition.getPropertyValues().getPropertyValue(propertyName)
|
||||
.getValue();
|
||||
}
|
||||
private BeanReference getConstructorBeanReference(BeanDefinition definition, int index) {
|
||||
|
||||
|
||||
private BeanReference getConstructorBeanReference(
|
||||
BeanDefinition definition, int index) {
|
||||
|
||||
Object value =
|
||||
definition.getConstructorArgumentValues()
|
||||
.getIndexedArgumentValues().get(index).getValue();
|
||||
assertTrue(value instanceof BeanReference);
|
||||
return (BeanReference) value;
|
||||
}
|
||||
Object value = definition.getConstructorArgumentValues().getIndexedArgumentValues().get(index).getValue();
|
||||
assertTrue(value instanceof BeanReference);
|
||||
return (BeanReference) value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractJpaEntityInformation}.
|
||||
*
|
||||
@@ -35,52 +34,45 @@ import org.mockito.runners.MockitoJUnitRunner;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaEntityInformationSupportUnitTests {
|
||||
|
||||
@Test
|
||||
public void usesSimpleClassNameIfNoEntityNameGiven() throws Exception {
|
||||
@Test
|
||||
public void usesSimpleClassNameIfNoEntityNameGiven() throws Exception {
|
||||
|
||||
JpaEntityInformation<User, Long> information =
|
||||
new DummyJpaEntityInformation<User, Long>(User.class);
|
||||
assertEquals("User", information.getEntityName());
|
||||
JpaEntityInformation<User, Long> information = new DummyJpaEntityInformation<User, Long>(User.class);
|
||||
assertEquals("User", information.getEntityName());
|
||||
|
||||
JpaEntityInformation<NamedUser, ?> second =
|
||||
new DummyJpaEntityInformation<NamedUser, Serializable>(
|
||||
NamedUser.class);
|
||||
assertEquals("AnotherNamedUser", second.getEntityName());
|
||||
}
|
||||
JpaEntityInformation<NamedUser, ?> second = new DummyJpaEntityInformation<NamedUser, Serializable>(NamedUser.class);
|
||||
assertEquals("AnotherNamedUser", second.getEntityName());
|
||||
}
|
||||
|
||||
static class User {
|
||||
static class User {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "AnotherNamedUser")
|
||||
public class NamedUser {
|
||||
@Entity(name = "AnotherNamedUser")
|
||||
public class NamedUser {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyJpaEntityInformation<T, ID extends Serializable> extends
|
||||
JpaEntityInformationSupport<T, ID> {
|
||||
static class DummyJpaEntityInformation<T, ID extends Serializable> extends JpaEntityInformationSupport<T, ID> {
|
||||
|
||||
public DummyJpaEntityInformation(Class<T> domainClass) {
|
||||
public DummyJpaEntityInformation(Class<T> domainClass) {
|
||||
|
||||
super(domainClass);
|
||||
}
|
||||
super(domainClass);
|
||||
}
|
||||
|
||||
public SingularAttribute<? super T, ?> getIdAttribute() {
|
||||
|
||||
public SingularAttribute<? super T, ?> getIdAttribute() {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public ID getId(T entity) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ID getId(T entity) {
|
||||
public Class<ID> getIdType() {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Class<ID> getIdType() {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.domain.Persistable;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link JpaPersistableEntityInformation}.
|
||||
*
|
||||
@@ -40,57 +39,52 @@ import org.springframework.data.repository.core.EntityInformation;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaPersistableEntityInformationUnitTests {
|
||||
|
||||
@Mock
|
||||
Metamodel metamodel;
|
||||
@Mock
|
||||
Metamodel metamodel;
|
||||
|
||||
@Mock
|
||||
EntityType<Foo> type;
|
||||
@Mock
|
||||
EntityType<Foo> type;
|
||||
|
||||
@Mock
|
||||
@SuppressWarnings("rawtypes")
|
||||
Type idType;
|
||||
@Mock
|
||||
@SuppressWarnings("rawtypes")
|
||||
Type idType;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setUp() {
|
||||
when(metamodel.entity(Foo.class)).thenReturn(type);
|
||||
when(type.getIdType()).thenReturn(idType);
|
||||
}
|
||||
|
||||
when(metamodel.entity(Foo.class)).thenReturn(type);
|
||||
when(type.getIdType()).thenReturn(idType);
|
||||
}
|
||||
@Test
|
||||
public void usesPersistableMethodsForIsNewAndGetId() {
|
||||
|
||||
EntityInformation<Foo, Long> entityInformation = new JpaPersistableEntityInformation<Foo, Long>(Foo.class,
|
||||
metamodel);
|
||||
|
||||
@Test
|
||||
public void usesPersistableMethodsForIsNewAndGetId() {
|
||||
Foo foo = new Foo();
|
||||
assertThat(entityInformation.isNew(foo), is(false));
|
||||
assertThat(entityInformation.getId(foo), is(nullValue()));
|
||||
|
||||
EntityInformation<Foo, Long> entityInformation =
|
||||
new JpaPersistableEntityInformation<Foo, Long>(Foo.class,
|
||||
metamodel);
|
||||
foo.id = 1L;
|
||||
assertThat(entityInformation.isNew(foo), is(true));
|
||||
assertThat(entityInformation.getId(foo), is(1L));
|
||||
}
|
||||
|
||||
Foo foo = new Foo();
|
||||
assertThat(entityInformation.isNew(foo), is(false));
|
||||
assertThat(entityInformation.getId(foo), is(nullValue()));
|
||||
@SuppressWarnings("serial")
|
||||
class Foo implements Persistable<Long> {
|
||||
|
||||
foo.id = 1L;
|
||||
assertThat(entityInformation.isNew(foo), is(true));
|
||||
assertThat(entityInformation.getId(foo), is(1L));
|
||||
}
|
||||
Long id;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class Foo implements Persistable<Long> {
|
||||
public Long getId() {
|
||||
|
||||
Long id;
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean isNew() {
|
||||
|
||||
public Long getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public boolean isNew() {
|
||||
|
||||
return id != null;
|
||||
}
|
||||
}
|
||||
return id != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,131 +38,114 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@code JpaRepositoryFactoryBean}.
|
||||
* <p>
|
||||
* TODO: Check if test methods double the ones in
|
||||
* {@link JpaRepositoryFactoryUnitTests}.
|
||||
* TODO: Check if test methods double the ones in {@link JpaRepositoryFactoryUnitTests}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaRepositoryFactoryBeanUnitTests {
|
||||
|
||||
JpaRepositoryFactoryBean<SimpleSampleRepository, User, Integer> factoryBean;
|
||||
JpaRepositoryFactoryBean<SimpleSampleRepository, User, Integer> factoryBean;
|
||||
|
||||
@Mock
|
||||
EntityManager entityManager;
|
||||
@Mock
|
||||
RepositoryFactorySupport factory;
|
||||
@Mock
|
||||
ListableBeanFactory beanFactory;
|
||||
@Mock
|
||||
PersistenceExceptionTranslator translator;
|
||||
@Mock
|
||||
Repository<?, ?> repository;
|
||||
@Mock
|
||||
EntityManager entityManager;
|
||||
@Mock
|
||||
RepositoryFactorySupport factory;
|
||||
@Mock
|
||||
ListableBeanFactory beanFactory;
|
||||
@Mock
|
||||
PersistenceExceptionTranslator translator;
|
||||
@Mock
|
||||
Repository<?, ?> repository;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setUp() {
|
||||
Map<String, PersistenceExceptionTranslator> beans = new HashMap<String, PersistenceExceptionTranslator>();
|
||||
beans.put("foo", translator);
|
||||
when(beanFactory.getBeansOfType(eq(PersistenceExceptionTranslator.class), anyBoolean(), anyBoolean())).thenReturn(
|
||||
beans);
|
||||
when(factory.getRepository(any(Class.class), any(Object.class))).thenReturn(repository);
|
||||
|
||||
Map<String, PersistenceExceptionTranslator> beans =
|
||||
new HashMap<String, PersistenceExceptionTranslator>();
|
||||
beans.put("foo", translator);
|
||||
when(
|
||||
beanFactory.getBeansOfType(
|
||||
eq(PersistenceExceptionTranslator.class), anyBoolean(),
|
||||
anyBoolean())).thenReturn(beans);
|
||||
when(factory.getRepository(any(Class.class), any(Object.class)))
|
||||
.thenReturn(repository);
|
||||
// Setup standard factory configuration
|
||||
factoryBean = new DummyJpaRepositoryFactoryBean<SimpleSampleRepository, User, Integer>();
|
||||
factoryBean.setRepositoryInterface(SimpleSampleRepository.class);
|
||||
factoryBean.setEntityManager(entityManager);
|
||||
}
|
||||
|
||||
// Setup standard factory configuration
|
||||
factoryBean =
|
||||
new DummyJpaRepositoryFactoryBean<SimpleSampleRepository, User, Integer>();
|
||||
factoryBean.setRepositoryInterface(SimpleSampleRepository.class);
|
||||
factoryBean.setEntityManager(entityManager);
|
||||
}
|
||||
/**
|
||||
* Assert that the instance created for the standard configuration is a valid {@code UserRepository}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void setsUpBasicInstanceCorrectly() throws Exception {
|
||||
|
||||
factoryBean.setBeanFactory(beanFactory);
|
||||
factoryBean.afterPropertiesSet();
|
||||
|
||||
/**
|
||||
* Assert that the instance created for the standard configuration is a
|
||||
* valid {@code UserRepository}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void setsUpBasicInstanceCorrectly() throws Exception {
|
||||
assertNotNull(factoryBean.getObject());
|
||||
}
|
||||
|
||||
factoryBean.setBeanFactory(beanFactory);
|
||||
factoryBean.afterPropertiesSet();
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void requiresListableBeanFactory() throws Exception {
|
||||
|
||||
assertNotNull(factoryBean.getObject());
|
||||
}
|
||||
factoryBean.setBeanFactory(mock(BeanFactory.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the factory rejects calls to {@code JpaRepositoryFactoryBean#setRepositoryInterface(Class)} with
|
||||
* {@literal null} or any other parameter instance not implementing {@code Repository}.
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullRepositoryInterface() {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void requiresListableBeanFactory() throws Exception {
|
||||
factoryBean.setRepositoryInterface(null);
|
||||
}
|
||||
|
||||
factoryBean.setBeanFactory(mock(BeanFactory.class));
|
||||
}
|
||||
/**
|
||||
* Assert that the factory detects unset repository class and interface in
|
||||
* {@code JpaRepositoryFactoryBean#afterPropertiesSet()}.
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsUnsetRepositoryInterface() throws Exception {
|
||||
|
||||
factoryBean = new JpaRepositoryFactoryBean<SimpleSampleRepository, User, Integer>();
|
||||
factoryBean.afterPropertiesSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the factory rejects calls to
|
||||
* {@code JpaRepositoryFactoryBean#setRepositoryInterface(Class)} with
|
||||
* {@literal null} or any other parameter instance not implementing
|
||||
* {@code Repository}.
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsNullRepositoryInterface() {
|
||||
private class DummyJpaRepositoryFactoryBean<T extends JpaRepository<S, ID>, S, ID extends Serializable> extends
|
||||
JpaRepositoryFactoryBean<T, S, ID> {
|
||||
|
||||
factoryBean.setRepositoryInterface(null);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean
|
||||
* #createRepositoryFactory()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryFactorySupport doCreateRepositoryFactory() {
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the factory detects unset repository class and interface in
|
||||
* {@code JpaRepositoryFactoryBean#afterPropertiesSet()}.
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void preventsUnsetRepositoryInterface() throws Exception {
|
||||
private interface SimpleSampleRepository extends JpaRepository<User, Integer> {
|
||||
|
||||
factoryBean =
|
||||
new JpaRepositoryFactoryBean<SimpleSampleRepository, User, Integer>();
|
||||
factoryBean.afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
|
||||
private class DummyJpaRepositoryFactoryBean<T extends JpaRepository<S, ID>, S, ID extends Serializable>
|
||||
extends JpaRepositoryFactoryBean<T, S, ID> {
|
||||
/**
|
||||
* Helper class to make the factory use {@link PersistableMetadata} .
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static abstract class User implements Persistable<Long> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean
|
||||
* #createRepositoryFactory()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryFactorySupport doCreateRepositoryFactory() {
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
||||
private interface SimpleSampleRepository extends
|
||||
JpaRepository<User, Integer> {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to make the factory use {@link PersistableMetadata} .
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static abstract class User implements Persistable<Long> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
@@ -38,7 +38,6 @@ import org.springframework.data.querydsl.QueryDslPredicateExecutor;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@code JpaRepositoryFactory}.
|
||||
*
|
||||
@@ -47,177 +46,146 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaRepositoryFactoryUnitTests {
|
||||
|
||||
JpaRepositoryFactory factory;
|
||||
JpaRepositoryFactory factory;
|
||||
|
||||
@Mock
|
||||
EntityManager entityManager;
|
||||
@Mock
|
||||
@SuppressWarnings("rawtypes")
|
||||
JpaEntityInformation metadata;
|
||||
@Mock
|
||||
EntityManager entityManager;
|
||||
@Mock
|
||||
@SuppressWarnings("rawtypes")
|
||||
JpaEntityInformation metadata;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// Setup standard factory configuration
|
||||
factory = new JpaRepositoryFactory(entityManager) {
|
||||
|
||||
// Setup standard factory configuration
|
||||
factory = new JpaRepositoryFactory(entityManager) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> JpaEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> JpaEntityInformation<T, ID> getEntityInformation(
|
||||
Class<T> domainClass) {
|
||||
return metadata;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return metadata;
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Assert that the instance created for the standard configuration is a valid {@code UserRepository}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void setsUpBasicInstanceCorrectly() throws Exception {
|
||||
|
||||
assertNotNull(factory.getRepository(SimpleSampleRepository.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the instance created for the standard configuration is a
|
||||
* valid {@code UserRepository}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void setsUpBasicInstanceCorrectly() throws Exception {
|
||||
@Test
|
||||
public void allowsCallingOfObjectMethods() {
|
||||
|
||||
assertNotNull(factory.getRepository(SimpleSampleRepository.class));
|
||||
}
|
||||
SimpleSampleRepository repository = factory.getRepository(SimpleSampleRepository.class);
|
||||
|
||||
repository.hashCode();
|
||||
repository.toString();
|
||||
repository.equals(repository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowsCallingOfObjectMethods() {
|
||||
/**
|
||||
* Asserts that the factory recognized configured repository classes that contain custom method but no custom
|
||||
* implementation could be found. Furthremore the exception has to contain the name of the repository interface as for
|
||||
* a large repository configuration it's hard to find out where this error occured.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void capturesMissingCustomImplementationAndProvidesInterfacename() throws Exception {
|
||||
|
||||
SimpleSampleRepository repository =
|
||||
factory.getRepository(SimpleSampleRepository.class);
|
||||
try {
|
||||
factory.getRepository(SampleRepository.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage().contains(SampleRepository.class.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
repository.hashCode();
|
||||
repository.toString();
|
||||
repository.equals(repository);
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void handlesRuntimeExceptionsCorrectly() {
|
||||
|
||||
SampleRepository repository = factory.getRepository(SampleRepository.class, new SampleCustomRepositoryImpl());
|
||||
repository.throwingRuntimeException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the factory recognized configured repository classes that
|
||||
* contain custom method but no custom implementation could be found.
|
||||
* Furthremore the exception has to contain the name of the repository
|
||||
* interface as for a large repository configuration it's hard to find out
|
||||
* where this error occured.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void capturesMissingCustomImplementationAndProvidesInterfacename()
|
||||
throws Exception {
|
||||
@Test(expected = IOException.class)
|
||||
public void handlesCheckedExceptionsCorrectly() throws Exception {
|
||||
|
||||
try {
|
||||
factory.getRepository(SampleRepository.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage()
|
||||
.contains(SampleRepository.class.getName()));
|
||||
}
|
||||
}
|
||||
SampleRepository repository = factory.getRepository(SampleRepository.class, new SampleCustomRepositoryImpl());
|
||||
repository.throwingCheckedException();
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void createsProxyWithCustomBaseClass() {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void handlesRuntimeExceptionsCorrectly() {
|
||||
JpaRepositoryFactory factory = new CustomGenericJpaRepositoryFactory(entityManager);
|
||||
UserCustomExtendedRepository repository = factory.getRepository(UserCustomExtendedRepository.class);
|
||||
|
||||
SampleRepository repository =
|
||||
factory.getRepository(SampleRepository.class,
|
||||
new SampleCustomRepositoryImpl());
|
||||
repository.throwingRuntimeException();
|
||||
}
|
||||
repository.customMethod(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesQueryDslRepositoryIfInterfaceImplementsExecutor() {
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void handlesCheckedExceptionsCorrectly() throws Exception {
|
||||
when(metadata.getJavaType()).thenReturn(User.class);
|
||||
assertEquals(QueryDslJpaRepository.class,
|
||||
factory.getRepositoryBaseClass(new DefaultRepositoryMetadata(QueryDslSampleRepository.class)));
|
||||
|
||||
SampleRepository repository =
|
||||
factory.getRepository(SampleRepository.class,
|
||||
new SampleCustomRepositoryImpl());
|
||||
repository.throwingCheckedException();
|
||||
}
|
||||
try {
|
||||
QueryDslSampleRepository repository = factory.getRepository(QueryDslSampleRepository.class);
|
||||
assertEquals(QueryDslJpaRepository.class, ((Advised) repository).getTargetClass());
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e.getStackTrace()[0].getClassName(), is("org.springframework.data.querydsl.SimpleEntityPathResolver"));
|
||||
}
|
||||
}
|
||||
|
||||
private interface SimpleSampleRepository extends JpaRepository<User, Integer> {
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void createsProxyWithCustomBaseClass() {
|
||||
@Transactional
|
||||
User findOne(Integer id);
|
||||
}
|
||||
|
||||
JpaRepositoryFactory factory =
|
||||
new CustomGenericJpaRepositoryFactory(entityManager);
|
||||
UserCustomExtendedRepository repository =
|
||||
factory.getRepository(UserCustomExtendedRepository.class);
|
||||
/**
|
||||
* Sample interface to contain a custom method.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface SampleCustomRepository {
|
||||
|
||||
repository.customMethod(1);
|
||||
}
|
||||
void throwingRuntimeException();
|
||||
|
||||
void throwingCheckedException() throws IOException;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesQueryDslRepositoryIfInterfaceImplementsExecutor() {
|
||||
/**
|
||||
* Implementation of the custom repository interface.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class SampleCustomRepositoryImpl implements SampleCustomRepository {
|
||||
|
||||
when(metadata.getJavaType()).thenReturn(User.class);
|
||||
assertEquals(QueryDslJpaRepository.class,
|
||||
factory.getRepositoryBaseClass(new DefaultRepositoryMetadata(
|
||||
QueryDslSampleRepository.class)));
|
||||
public void throwingRuntimeException() {
|
||||
|
||||
try {
|
||||
QueryDslSampleRepository repository =
|
||||
factory.getRepository(QueryDslSampleRepository.class);
|
||||
assertEquals(QueryDslJpaRepository.class,
|
||||
((Advised) repository).getTargetClass());
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(
|
||||
e.getStackTrace()[0].getClassName(),
|
||||
is("org.springframework.data.querydsl.SimpleEntityPathResolver"));
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("You lose!");
|
||||
}
|
||||
|
||||
private interface SimpleSampleRepository extends
|
||||
JpaRepository<User, Integer> {
|
||||
public void throwingCheckedException() throws IOException {
|
||||
|
||||
@Transactional
|
||||
User findOne(Integer id);
|
||||
}
|
||||
throw new IOException("You lose!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample interface to contain a custom method.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface SampleCustomRepository {
|
||||
private interface SampleRepository extends JpaRepository<User, Integer>, SampleCustomRepository {
|
||||
|
||||
void throwingRuntimeException();
|
||||
}
|
||||
|
||||
private interface QueryDslSampleRepository extends SimpleSampleRepository, QueryDslPredicateExecutor<User> {
|
||||
|
||||
void throwingCheckedException() throws IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the custom repository interface.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class SampleCustomRepositoryImpl implements SampleCustomRepository {
|
||||
|
||||
public void throwingRuntimeException() {
|
||||
|
||||
throw new IllegalArgumentException("You lose!");
|
||||
}
|
||||
|
||||
|
||||
public void throwingCheckedException() throws IOException {
|
||||
|
||||
throw new IOException("You lose!");
|
||||
}
|
||||
}
|
||||
|
||||
private interface SampleRepository extends JpaRepository<User, Integer>,
|
||||
SampleCustomRepository {
|
||||
|
||||
}
|
||||
|
||||
private interface QueryDslSampleRepository extends SimpleSampleRepository,
|
||||
QueryDslPredicateExecutor<User> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for {@link JpaRepository}.
|
||||
*
|
||||
@@ -44,37 +43,31 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Transactional
|
||||
public class JpaRepositoryTests {
|
||||
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
|
||||
JpaRepository<SampleEntity, SampleEntityPK> repository;
|
||||
JpaRepository<SampleEntity, SampleEntityPK> repository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
repository = new JpaRepositoryFactory(em).getRepository(SampleEntityRepository.class);
|
||||
}
|
||||
|
||||
repository =
|
||||
new JpaRepositoryFactory(em)
|
||||
.getRepository(SampleEntityRepository.class);
|
||||
}
|
||||
@Test
|
||||
public void testCrudOperationsForCompoundKeyEntity() throws Exception {
|
||||
|
||||
SampleEntity entity = new SampleEntity("foo", "bar");
|
||||
repository.saveAndFlush(entity);
|
||||
assertThat(repository.count(), is(1L));
|
||||
assertThat(repository.findOne(new SampleEntityPK("foo", "bar")), is(entity));
|
||||
|
||||
@Test
|
||||
public void testCrudOperationsForCompoundKeyEntity() throws Exception {
|
||||
repository.delete(Arrays.asList(entity));
|
||||
repository.flush();
|
||||
assertThat(repository.count(), is(0L));
|
||||
}
|
||||
|
||||
SampleEntity entity = new SampleEntity("foo", "bar");
|
||||
repository.saveAndFlush(entity);
|
||||
assertThat(repository.count(), is(1L));
|
||||
assertThat(repository.findOne(new SampleEntityPK("foo", "bar")),
|
||||
is(entity));
|
||||
private static interface SampleEntityRepository extends JpaRepository<SampleEntity, SampleEntityPK> {
|
||||
|
||||
repository.delete(Arrays.asList(entity));
|
||||
repository.flush();
|
||||
assertThat(repository.count(), is(0L));
|
||||
}
|
||||
|
||||
private static interface SampleEntityRepository extends
|
||||
JpaRepository<SampleEntity, SampleEntityPK> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,5 +22,5 @@ package org.springframework.data.jpa.repository.support;
|
||||
*/
|
||||
class QSimpleEntityPathResolverUnitTests_Sample {
|
||||
|
||||
public QSimpleEntityPathResolverUnitTests_Sample field;
|
||||
public QSimpleEntityPathResolverUnitTests_Sample field;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.mysema.query.types.expr.BooleanExpression;
|
||||
import com.mysema.query.types.path.PathBuilder;
|
||||
import com.mysema.query.types.path.PathBuilderFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for {@link QueryDslJpaRepository}.
|
||||
*
|
||||
@@ -47,57 +46,47 @@ import com.mysema.query.types.path.PathBuilderFactory;
|
||||
@Transactional
|
||||
public class QueryDslJpaRepositoryTests {
|
||||
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
|
||||
QueryDslJpaRepository<User, Integer> repository;
|
||||
QUser user = new QUser("user");
|
||||
User dave, carter;
|
||||
QueryDslJpaRepository<User, Integer> repository;
|
||||
QUser user = new QUser("user");
|
||||
User dave, carter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
JpaEntityInformation<User, Integer> information = new JpaMetamodelEntityInformation<User, Integer>(User.class,
|
||||
em.getMetamodel());
|
||||
|
||||
JpaEntityInformation<User, Integer> information =
|
||||
new JpaMetamodelEntityInformation<User, Integer>(User.class,
|
||||
em.getMetamodel());
|
||||
repository = new QueryDslJpaRepository<User, Integer>(information, em);
|
||||
dave = repository.save(new User("Dave", "Matthews", "dave@matthews.com"));
|
||||
carter = repository.save(new User("Carter", "Beauford", "carter@beauford.com"));
|
||||
}
|
||||
|
||||
repository = new QueryDslJpaRepository<User, Integer>(information, em);
|
||||
dave =
|
||||
repository.save(new User("Dave", "Matthews",
|
||||
"dave@matthews.com"));
|
||||
carter =
|
||||
repository.save(new User("Carter", "Beauford",
|
||||
"carter@beauford.com"));
|
||||
}
|
||||
@Test
|
||||
public void executesPredicatesCorrectly() throws Exception {
|
||||
|
||||
BooleanExpression isCalledDave = user.firstname.eq("Dave");
|
||||
BooleanExpression isBeauford = user.lastname.eq("Beauford");
|
||||
|
||||
@Test
|
||||
public void executesPredicatesCorrectly() throws Exception {
|
||||
List<User> result = repository.findAll(isCalledDave.or(isBeauford));
|
||||
|
||||
BooleanExpression isCalledDave = user.firstname.eq("Dave");
|
||||
BooleanExpression isBeauford = user.lastname.eq("Beauford");
|
||||
assertThat(result.size(), is(2));
|
||||
assertThat(result, hasItems(carter, dave));
|
||||
}
|
||||
|
||||
List<User> result = repository.findAll(isCalledDave.or(isBeauford));
|
||||
@Test
|
||||
public void executesStringBasedPredicatesCorrectly() throws Exception {
|
||||
|
||||
assertThat(result.size(), is(2));
|
||||
assertThat(result, hasItems(carter, dave));
|
||||
}
|
||||
PathBuilder<User> builder = new PathBuilderFactory().create(User.class);
|
||||
|
||||
BooleanExpression isCalledDave = builder.getString("firstname").eq("Dave");
|
||||
BooleanExpression isBeauford = builder.getString("lastname").eq("Beauford");
|
||||
|
||||
@Test
|
||||
public void executesStringBasedPredicatesCorrectly() throws Exception {
|
||||
List<User> result = repository.findAll(isCalledDave.or(isBeauford));
|
||||
|
||||
PathBuilder<User> builder = new PathBuilderFactory().create(User.class);
|
||||
|
||||
BooleanExpression isCalledDave =
|
||||
builder.getString("firstname").eq("Dave");
|
||||
BooleanExpression isBeauford =
|
||||
builder.getString("lastname").eq("Beauford");
|
||||
|
||||
List<User> result = repository.findAll(isCalledDave.or(isBeauford));
|
||||
|
||||
assertThat(result.size(), is(2));
|
||||
assertThat(result, hasItems(carter, dave));
|
||||
}
|
||||
assertThat(result.size(), is(2));
|
||||
assertThat(result, hasItems(carter, dave));
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user